blob: 0ec893e39d751fa656f174b5c3df9aabe8bf89f7 [file] [log] [blame]
developer9198e8b2024-02-22 06:01:52 +08001#!/bin/sh
2. /lib/netifd/netifd-wireless.sh
3. /lib/netifd/hostapd.sh
4. /lib/functions/system.sh
5
6init_wireless_driver "$@"
7
8MP_CONFIG_INT="mesh_retry_timeout mesh_confirm_timeout mesh_holding_timeout mesh_max_peer_links
9 mesh_max_retries mesh_ttl mesh_element_ttl mesh_hwmp_max_preq_retries
10 mesh_path_refresh_time mesh_min_discovery_timeout mesh_hwmp_active_path_timeout
11 mesh_hwmp_preq_min_interval mesh_hwmp_net_diameter_traversal_time mesh_hwmp_rootmode
12 mesh_hwmp_rann_interval mesh_gate_announcements mesh_sync_offset_max_neighor
13 mesh_rssi_threshold mesh_hwmp_active_path_to_root_timeout mesh_hwmp_root_interval
14 mesh_hwmp_confirmation_interval mesh_awake_window mesh_plink_timeout"
15MP_CONFIG_BOOL="mesh_auto_open_plinks mesh_fwding"
16MP_CONFIG_STRING="mesh_power_mode"
17
18wdev_tool() {
19 ucode /usr/share/hostap/wdev.uc "$@"
20}
21
22ubus_call() {
23 flock /var/run/hostapd.lock ubus call "$@"
24}
25
26drv_mac80211_init_device_config() {
27 hostapd_common_add_device_config
28
29 config_add_string path phy 'macaddr:macaddr'
30 config_add_string tx_burst
31 config_add_string distance
developer5cd6ced2024-03-21 15:48:34 +080032 config_add_int mbssid mu_onoff sr_enable sr_enhanced rnr obss_interval band_idx
developer9198e8b2024-02-22 06:01:52 +080033 config_add_int beacon_int chanbw frag rts
34 config_add_int rxantenna txantenna txpower min_tx_power
35 config_add_int num_global_macaddr multiple_bssid
36 config_add_boolean noscan ht_coex acs_exclude_dfs background_radar
37 config_add_boolean noscan ht_coex acs_exclude_dfs background_radar background_cert_mode
38 config_add_array ht_capab
39 config_add_array channels
40 config_add_array scan_list
41 config_add_boolean \
42 rxldpc \
43 short_gi_80 \
44 short_gi_160 \
45 tx_stbc_2by1 \
46 su_beamformer \
47 su_beamformee \
48 mu_beamformer \
49 mu_beamformee \
50 he_su_beamformer \
51 he_su_beamformee \
52 he_mu_beamformer \
53 vht_txop_ps \
54 htc_vht \
55 rx_antenna_pattern \
56 tx_antenna_pattern \
57 he_spr_sr_control \
58 he_spr_psr_enabled \
59 he_bss_color_enabled \
60 he_twt_required \
61 he_twt_responder \
62 etxbfen \
63 itxbfen
64 config_add_int \
65 beamformer_antennas \
66 beamformee_antennas \
67 vht_max_a_mpdu_len_exp \
68 vht_max_mpdu \
69 vht_link_adapt \
70 vht160 \
71 rx_stbc \
72 tx_stbc \
73 he_bss_color \
developer5f1d3ca2024-04-25 05:25:22 +080074 he_spr_non_srg_obss_pd_max_offset \
75 pp_bitmap \
76 pp_mode
developer9198e8b2024-02-22 06:01:52 +080077 config_add_boolean \
78 ldpc \
79 greenfield \
80 short_gi_20 \
81 short_gi_40 \
82 max_amsdu \
83 dsss_cck_40
84}
85
86drv_mac80211_init_iface_config() {
87 hostapd_common_add_bss_config
88
89 config_add_string 'macaddr:macaddr' ifname
90
91 config_add_boolean wds powersave enable
92 config_add_string wds_bridge
93 config_add_int maxassoc
94 config_add_int max_listen_int
95 config_add_int dtim_period
96 config_add_int start_disabled
developer2bedae82024-04-23 04:47:06 +080097 config_add_int vif_txpower
developer9198e8b2024-02-22 06:01:52 +080098
99 # mesh
100 config_add_string mesh_id
101 config_add_int $MP_CONFIG_INT
102 config_add_boolean $MP_CONFIG_BOOL
103 config_add_string $MP_CONFIG_STRING
104}
105
106mac80211_add_capabilities() {
107 local __var="$1"; shift
108 local __mask="$1"; shift
109 local __out= oifs
110
111 oifs="$IFS"
112 IFS=:
113 for capab in "$@"; do
114 set -- $capab
115
116 [ "$(($4))" -gt 0 ] || continue
117 [ "$(($__mask & $2))" -eq "$((${3:-$2}))" ] || continue
118 __out="$__out[$1]"
119 done
120 IFS="$oifs"
121
122 export -n -- "$__var=$__out"
123}
124
125mac80211_add_he_capabilities() {
126 local __out= oifs
127
128 oifs="$IFS"
129 IFS=:
130 for capab in "$@"; do
131 set -- $capab
132 [ "$(($4))" -gt 0 ] || continue
133 [ "$(((0x$2) & $3))" -gt 0 ] || {
134 eval "$1=0"
135 continue
136 }
137 append base_cfg "$1=1" "$N"
138 done
139 IFS="$oifs"
140}
141
142mac80211_hostapd_setup_base() {
143 local phy="$1"
144
145 json_select config
146
147 [ "$auto_channel" -gt 0 ] && channel=acs_survey
148
149 [ "$auto_channel" -gt 0 ] && json_get_vars acs_exclude_dfs
150 [ -n "$acs_exclude_dfs" ] && [ "$acs_exclude_dfs" -gt 0 ] &&
151 append base_cfg "acs_exclude_dfs=1" "$N"
152
developer5cd6ced2024-03-21 15:48:34 +0800153 json_get_vars noscan ht_coex min_tx_power:0 tx_burst mbssid mu_onoff rnr obss_interval band_idx
developer9198e8b2024-02-22 06:01:52 +0800154 json_get_vars etxbfen:1 itxbfen:0
155 json_get_values ht_capab_list ht_capab
156 json_get_values channel_list channels
157
158 [ "$min_tx_power" -gt 0 ] && append base_cfg "min_tx_power=$min_tx_power" "$N"
159
160 set_default noscan 0
161
162 [ "$noscan" -gt 0 ] && hostapd_noscan=1
163 [ "$tx_burst" = 0 ] && tx_burst=
164
165 chan_ofs=0
166 [ "$band" = "6g" ] && chan_ofs=1
167
168 ieee80211n=1
169 ht_capab=
170 case "$htmode" in
171 VHT20|HT20|HE20|EHT20) ;;
172 HT40*|VHT40|VHT80|VHT160|HE40*|HE80|HE160|EHT40*|EHT80|EHT160|EHT320*)
173 case "$hwmode" in
174 a)
175 case "$(( (($channel / 4) + $chan_ofs) % 2 ))" in
176 1) ht_capab="[HT40+]";;
177 0) ht_capab="[HT40-]";;
178 esac
179 case "$htmode" in
180 HT40-|HE40-|EHT40-)
181 if [ "$auto_channel" -gt 0 ]; then
182 ht_capab="[HT40-]"
183 fi
184 ;;
185 esac
186 ;;
187 *)
188 case "$htmode" in
189 HT40+|HE40+|EHT40+)
190 if [ "$channel" -gt 9 ]; then
191 echo "Could not set the center freq with this HT mode setting"
192 return 1
193 else
194 ht_capab="[HT40+]"
195 fi
196 ;;
197 HT40-|HE40-|EHT40-)
198 if [ "$channel" -lt 5 -a "$auto_channel" -eq 0 ]; then
199 echo "Could not set the center freq with this HT mode setting"
200 return 1
201 else
202 ht_capab="[HT40-]"
203 fi
204 ;;
205 *)
206 if [ "$channel" -lt 7 -o "$auto_channel" -gt 0 ]; then
207 ht_capab="[HT40+]"
208 else
209 ht_capab="[HT40-]"
210 fi
211 ;;
212 esac
213 ;;
214 esac
215 ;;
216 *) ieee80211n= ;;
217 esac
218
219 [ -n "$ieee80211n" ] && {
220 append base_cfg "ieee80211n=1" "$N"
221
222 set_default ht_coex 0
223 append base_cfg "ht_coex=$ht_coex" "$N"
224
225 [ "$ht_coex" -eq 1 ] && {
226 set_default obss_interval 300
227 append base_cfg "obss_interval=$obss_interval" "$N"
228 }
229
230 json_get_vars \
231 ldpc:1 \
232 greenfield:0 \
233 short_gi_20:1 \
234 short_gi_40:1 \
235 tx_stbc:1 \
236 rx_stbc:3 \
237 max_amsdu:1 \
238 dsss_cck_40:1
239
240 ht_cap_mask=0
241 for cap in $(iw phy "$phy" info | grep 'Capabilities: 0x' | cut -d: -f2); do
242 ht_cap_mask="$(($ht_cap_mask | $cap))"
243 done
244
245 cap_rx_stbc=$((($ht_cap_mask >> 8) & 3))
246 [ "$rx_stbc" -lt "$cap_rx_stbc" ] && cap_rx_stbc="$rx_stbc"
247 ht_cap_mask="$(( ($ht_cap_mask & ~(0x300)) | ($cap_rx_stbc << 8) ))"
248
249 mac80211_add_capabilities ht_capab_flags $ht_cap_mask \
250 LDPC:0x1::$ldpc \
251 GF:0x10::$greenfield \
252 SHORT-GI-20:0x20::$short_gi_20 \
253 SHORT-GI-40:0x40::$short_gi_40 \
254 TX-STBC:0x80::$tx_stbc \
255 RX-STBC1:0x300:0x100:1 \
256 RX-STBC12:0x300:0x200:1 \
257 RX-STBC123:0x300:0x300:1 \
258 MAX-AMSDU-7935:0x800::$max_amsdu \
259 DSSS_CCK-40:0x1000::$dsss_cck_40
260
261 ht_capab="$ht_capab$ht_capab_flags"
262 [ -n "$ht_capab" ] && append base_cfg "ht_capab=$ht_capab" "$N"
263 }
264
265 # 802.11ac
266 enable_ac=0
267 vht_oper_chwidth=0
268 vht_center_seg0=
269
270 idx="$channel"
271 case "$htmode" in
272 VHT20|HE20|EHT20) enable_ac=1;;
273 VHT40|HE40|EHT40)
274 case "$(( (($channel / 4) + $chan_ofs) % 2 ))" in
275 1) idx=$(($channel + 2));;
276 0) idx=$(($channel - 2));;
277 esac
278 enable_ac=1
279 vht_center_seg0=$idx
280 ;;
281 VHT80|HE80|EHT80)
282 case "$(( (($channel / 4) + $chan_ofs) % 4 ))" in
283 1) idx=$(($channel + 6));;
284 2) idx=$(($channel + 2));;
285 3) idx=$(($channel - 2));;
286 0) idx=$(($channel - 6));;
287 esac
288 enable_ac=1
289 vht_oper_chwidth=1
290 vht_center_seg0=$idx
291 ;;
292 VHT160|HE160|EHT160)
293 if [ "$band" = "6g" ]; then
294 case "$channel" in
295 1|5|9|13|17|21|25|29) idx=15;;
296 33|37|41|45|49|53|57|61) idx=47;;
297 65|69|73|77|81|85|89|93) idx=79;;
298 97|101|105|109|113|117|121|125) idx=111;;
299 129|133|137|141|145|149|153|157) idx=143;;
300 161|165|169|173|177|181|185|189) idx=175;;
301 193|197|201|205|209|213|217|221) idx=207;;
302 esac
303 else
304 case "$channel" in
305 36|40|44|48|52|56|60|64) idx=50;;
306 100|104|108|112|116|120|124|128) idx=114;;
307 149|153|157|161|165|169|173|177) idx=163;;
308 esac
309 fi
310 enable_ac=1
311 vht_oper_chwidth=2
312 vht_center_seg0=$idx
313 ;;
314 EHT320*)
315 case "$channel" in
316 1|5|9|13|17|21|25|29) idx=31;;
317 33|37|41|45|49|53|57|61| \
318 65|69|73|77|81|85|89|93) idx=63;;
319 97|101|105|109|113|117|121|125| \
320 129|133|137|141|145|149|153|157) idx=127;;
321 161|165|169|173|177|181|185|189| \
322 193|197|201|205|209|213|217|221) idx=191;;
323 esac
324 if [[ "$htmode" = "EHT320-1" && "$channel" -ge "193" ]] ||
325 [[ "$htmode" = "EHT320-2" && "$channel" -le "29" ]]; then
326 echo "Could not set the center freq with this EHT setting"
327 return 1
328 elif [[ "$htmode" = "EHT320-1" && "$channel" -ge "33" ]]; then
329 if [ "$channel" -gt $idx ]; then
330 idx=$(($idx + 32))
331 else
332 idx=$(($idx - 32))
333 fi
334 fi
335 vht_oper_chwidth=2
336 if [ "$channel" -gt $idx ]; then
337 vht_center_seg0=$(($idx + 16))
338 else
339 vht_center_seg0=$(($idx - 16))
340 fi
341 eht_oper_chwidth=9
342 eht_oper_centr_freq_seg0_idx=$idx
343
344 case $htmode in
345 EHT320-1) eht_bw320_offset=1;;
346 EHT320-2) eht_bw320_offset=2;;
347 EHT320) eht_bw320_offset=0;;
348 esac
349 ;;
350 esac
351 [ "$band" = "5g" ] && {
352 json_get_vars \
353 background_radar:0 \
354 background_cert_mode:0 \
355
356 [ "$background_radar" -eq 1 ] && append base_cfg "enable_background_radar=1" "$N"
357 [ "$background_cert_mode" -eq 1 ] && append base_cfg "background_radar_mode=1" "$N"
358 }
359 [ "$band" = "6g" ] && {
360 op_class=
361 case "$htmode" in
362 HE20|EHT20) op_class=131;;
363 EHT320*) op_class=137;;
364 HE*|EHT*) op_class=$((132 + $vht_oper_chwidth))
365 esac
366 [ -n "$op_class" ] && append base_cfg "op_class=$op_class" "$N"
367 }
368 [ "$hwmode" = "a" ] || enable_ac=0
369
370 if [ "$enable_ac" != "0" ]; then
371 json_get_vars \
372 rxldpc:1 \
373 short_gi_80:1 \
374 short_gi_160:1 \
375 tx_stbc_2by1:1 \
376 su_beamformer:1 \
377 su_beamformee:1 \
378 mu_beamformer:1 \
379 mu_beamformee:1 \
380 vht_txop_ps:1 \
381 htc_vht:1 \
developerb537dd92024-04-22 00:51:57 +0800382 beamformee_antennas:5 \
developer9198e8b2024-02-22 06:01:52 +0800383 beamformer_antennas:4 \
384 rx_antenna_pattern:1 \
385 tx_antenna_pattern:1 \
386 vht_max_a_mpdu_len_exp:7 \
387 vht_max_mpdu:11454 \
388 rx_stbc:4 \
389 vht_link_adapt:3 \
390 vht160:2
391
392 append base_cfg "ieee80211ac=1" "$N"
393 vht_cap=0
394 for cap in $(iw phy "$phy" info | awk -F "[()]" '/VHT Capabilities/ { print $2 }'); do
395 vht_cap="$(($vht_cap | $cap))"
396 done
397
398 append base_cfg "vht_oper_chwidth=$vht_oper_chwidth" "$N"
399 append base_cfg "vht_oper_centr_freq_seg0_idx=$vht_center_seg0" "$N"
400
401 cap_rx_stbc=$((($vht_cap >> 8) & 7))
402 [ "$rx_stbc" -lt "$cap_rx_stbc" ] && cap_rx_stbc="$rx_stbc"
403 vht_cap="$(( ($vht_cap & ~(0x700)) | ($cap_rx_stbc << 8) ))"
404
405 [ "$vht_oper_chwidth" -lt 2 ] && {
406 vht160=0
407 short_gi_160=0
408 }
409
410 [ "$etxbfen" -eq 0 ] && {
411 su_beamformer=0
412 su_beamformee=0
413 mu_beamformer=0
414 }
415
416 mac80211_add_capabilities vht_capab $vht_cap \
417 RXLDPC:0x10::$rxldpc \
418 SHORT-GI-80:0x20::$short_gi_80 \
419 SHORT-GI-160:0x40::$short_gi_160 \
420 TX-STBC-2BY1:0x80::$tx_stbc_2by1 \
421 SU-BEAMFORMER:0x800::$su_beamformer \
422 SU-BEAMFORMEE:0x1000::$su_beamformee \
423 MU-BEAMFORMER:0x80000::$mu_beamformer \
424 MU-BEAMFORMEE:0x100000::$mu_beamformee \
425 VHT-TXOP-PS:0x200000::$vht_txop_ps \
426 HTC-VHT:0x400000::$htc_vht \
427 RX-ANTENNA-PATTERN:0x10000000::$rx_antenna_pattern \
428 TX-ANTENNA-PATTERN:0x20000000::$tx_antenna_pattern \
429 RX-STBC-1:0x700:0x100:1 \
430 RX-STBC-12:0x700:0x200:1 \
431 RX-STBC-123:0x700:0x300:1 \
432 RX-STBC-1234:0x700:0x400:1 \
433
434 [ "$(($vht_cap & 0x800))" -gt 0 -a "$su_beamformer" -gt 0 ] && {
435 cap_ant="$(( ( ($vht_cap >> 16) & 3 ) + 1 ))"
436 [ "$cap_ant" -gt "$beamformer_antennas" ] && cap_ant="$beamformer_antennas"
437 [ "$cap_ant" -gt 1 ] && vht_capab="$vht_capab[SOUNDING-DIMENSION-$cap_ant]"
438 }
439
440 [ "$(($vht_cap & 0x1000))" -gt 0 -a "$su_beamformee" -gt 0 ] && {
developerb537dd92024-04-22 00:51:57 +0800441 cap_ant="$(( ( ($vht_cap >> 13) & 7 ) + 1 ))"
developer9198e8b2024-02-22 06:01:52 +0800442 [ "$cap_ant" -gt "$beamformee_antennas" ] && cap_ant="$beamformee_antennas"
443 [ "$cap_ant" -gt 1 ] && vht_capab="$vht_capab[BF-ANTENNA-$cap_ant]"
444 }
445
446 # supported Channel widths
447 vht160_hw=0
448 [ "$(($vht_cap & 12))" -eq 4 -a 1 -le "$vht160" ] && \
449 vht160_hw=1
450 [ "$(($vht_cap & 12))" -eq 8 -a 2 -le "$vht160" ] && \
451 vht160_hw=2
452 [ "$vht160_hw" = 1 ] && vht_capab="$vht_capab[VHT160]"
453 [ "$vht160_hw" = 2 ] && vht_capab="$vht_capab[VHT160-80PLUS80]"
454
455 # maximum MPDU length
456 vht_max_mpdu_hw=3895
457 [ "$(($vht_cap & 3))" -ge 1 -a 7991 -le "$vht_max_mpdu" ] && \
458 vht_max_mpdu_hw=7991
459 [ "$(($vht_cap & 3))" -ge 2 -a 11454 -le "$vht_max_mpdu" ] && \
460 vht_max_mpdu_hw=11454
461 [ "$vht_max_mpdu_hw" != 3895 ] && \
462 vht_capab="$vht_capab[MAX-MPDU-$vht_max_mpdu_hw]"
463
464 # maximum A-MPDU length exponent
465 vht_max_a_mpdu_len_exp_hw=0
466 [ "$(($vht_cap & 58720256))" -ge 8388608 -a 1 -le "$vht_max_a_mpdu_len_exp" ] && \
467 vht_max_a_mpdu_len_exp_hw=1
468 [ "$(($vht_cap & 58720256))" -ge 16777216 -a 2 -le "$vht_max_a_mpdu_len_exp" ] && \
469 vht_max_a_mpdu_len_exp_hw=2
470 [ "$(($vht_cap & 58720256))" -ge 25165824 -a 3 -le "$vht_max_a_mpdu_len_exp" ] && \
471 vht_max_a_mpdu_len_exp_hw=3
472 [ "$(($vht_cap & 58720256))" -ge 33554432 -a 4 -le "$vht_max_a_mpdu_len_exp" ] && \
473 vht_max_a_mpdu_len_exp_hw=4
474 [ "$(($vht_cap & 58720256))" -ge 41943040 -a 5 -le "$vht_max_a_mpdu_len_exp" ] && \
475 vht_max_a_mpdu_len_exp_hw=5
476 [ "$(($vht_cap & 58720256))" -ge 50331648 -a 6 -le "$vht_max_a_mpdu_len_exp" ] && \
477 vht_max_a_mpdu_len_exp_hw=6
478 [ "$(($vht_cap & 58720256))" -ge 58720256 -a 7 -le "$vht_max_a_mpdu_len_exp" ] && \
479 vht_max_a_mpdu_len_exp_hw=7
480 vht_capab="$vht_capab[MAX-A-MPDU-LEN-EXP$vht_max_a_mpdu_len_exp_hw]"
481
482 # whether or not the STA supports link adaptation using VHT variant
483 vht_link_adapt_hw=0
484 [ "$(($vht_cap & 201326592))" -ge 134217728 -a 2 -le "$vht_link_adapt" ] && \
485 vht_link_adapt_hw=2
486 [ "$(($vht_cap & 201326592))" -ge 201326592 -a 3 -le "$vht_link_adapt" ] && \
487 vht_link_adapt_hw=3
488 [ "$vht_link_adapt_hw" != 0 ] && \
489 vht_capab="$vht_capab[VHT-LINK-ADAPT-$vht_link_adapt_hw]"
490
491 [ -n "$vht_capab" ] && append base_cfg "vht_capab=$vht_capab" "$N"
492 fi
493
494 # 802.11ax
495 enable_ax=0
496 case "$htmode" in
497 HE*|EHT*) enable_ax=1 ;;
498 esac
499
500 if [ "$enable_ax" != "0" ]; then
501 json_get_vars \
502 he_su_beamformer:1 \
503 he_su_beamformee:1 \
504 he_mu_beamformer:1 \
505 he_twt_required:0 \
506 he_twt_responder \
507 he_spr_sr_control:3 \
508 he_spr_psr_enabled:0 \
509 he_spr_non_srg_obss_pd_max_offset:0 \
510 he_bss_color \
511 he_bss_color_enabled:1
512
513 he_phy_cap=$(iw phy "$phy" info | sed -n '/HE Iftypes: AP/,$p' | awk -F "[()]" '/HE PHY Capabilities/ { print $2 }' | head -1)
514 he_phy_cap=${he_phy_cap:2}
515 he_mac_cap=$(iw phy "$phy" info | sed -n '/HE Iftypes: AP/,$p' | awk -F "[()]" '/HE MAC Capabilities/ { print $2 }' | head -1)
516 he_mac_cap=${he_mac_cap:2}
517
518 append base_cfg "ieee80211ax=1" "$N"
519 [ "$hwmode" = "a" ] && {
520 append base_cfg "he_oper_chwidth=$vht_oper_chwidth" "$N"
521 append base_cfg "he_oper_centr_freq_seg0_idx=$vht_center_seg0" "$N"
522 }
523
524 [ "$etxbfen" -eq 0 ] && {
525 he_su_beamformer=0
526 he_mu_beamformer=0
527 }
528
529 mac80211_add_he_capabilities \
530 he_su_beamformer:${he_phy_cap:6:2}:0x80:$he_su_beamformer \
531 he_su_beamformee:${he_phy_cap:8:2}:0x1:$he_su_beamformee \
532 he_mu_beamformer:${he_phy_cap:8:2}:0x2:$he_mu_beamformer \
533 he_spr_psr_enabled:${he_phy_cap:14:2}:0x1:$he_spr_psr_enabled \
534 he_twt_required:${he_mac_cap:0:2}:0x6:$he_twt_required
535
536 if [ -n "$he_twt_responder" ]; then
537 append base_cfg "he_twt_responder=$he_twt_responder" "$N"
538 fi
539 if [ "$he_bss_color_enabled" -gt 0 ]; then
540 if !([ "$he_bss_color" -gt 0 ] && [ "$he_bss_color" -le 64 ]); then
541 rand=$(head -n 1 /dev/urandom | tr -dc 0-9 | head -c 2)
542 he_bss_color=$((rand % 63 + 1))
543 fi
544 append base_cfg "he_bss_color=$he_bss_color" "$N"
545 [ "$he_spr_non_srg_obss_pd_max_offset" -gt 0 ] && { \
546 append base_cfg "he_spr_non_srg_obss_pd_max_offset=$he_spr_non_srg_obss_pd_max_offset" "$N"
547 he_spr_sr_control=$((he_spr_sr_control | (1 << 2)))
548 }
549 [ "$he_spr_psr_enabled" -gt 0 ] || he_spr_sr_control=$((he_spr_sr_control | (1 << 0)))
550 append base_cfg "he_spr_sr_control=$he_spr_sr_control" "$N"
551 else
552 append base_cfg "he_bss_color_disabled=1" "$N"
553 fi
554
555
556 append base_cfg "he_default_pe_duration=4" "$N"
557 append base_cfg "he_rts_threshold=1023" "$N"
558 append base_cfg "he_mu_edca_qos_info_param_count=0" "$N"
559 append base_cfg "he_mu_edca_qos_info_q_ack=0" "$N"
560 append base_cfg "he_mu_edca_qos_info_queue_request=0" "$N"
561 append base_cfg "he_mu_edca_qos_info_txop_request=0" "$N"
562 append base_cfg "he_mu_edca_ac_be_aifsn=0" "$N"
563 append base_cfg "he_mu_edca_ac_be_aci=0" "$N"
564 append base_cfg "he_mu_edca_ac_be_ecwmin=9" "$N"
565 append base_cfg "he_mu_edca_ac_be_ecwmax=10" "$N"
566 append base_cfg "he_mu_edca_ac_be_timer=3" "$N"
567 append base_cfg "he_mu_edca_ac_bk_aifsn=0" "$N"
568 append base_cfg "he_mu_edca_ac_bk_aci=1" "$N"
569 append base_cfg "he_mu_edca_ac_bk_ecwmin=9" "$N"
570 append base_cfg "he_mu_edca_ac_bk_ecwmax=10" "$N"
571 append base_cfg "he_mu_edca_ac_bk_timer=3" "$N"
572 append base_cfg "he_mu_edca_ac_vi_ecwmin=5" "$N"
573 append base_cfg "he_mu_edca_ac_vi_ecwmax=7" "$N"
574 append base_cfg "he_mu_edca_ac_vi_aifsn=0" "$N"
575 append base_cfg "he_mu_edca_ac_vi_aci=2" "$N"
576 append base_cfg "he_mu_edca_ac_vi_timer=3" "$N"
577 append base_cfg "he_mu_edca_ac_vo_aifsn=0" "$N"
578 append base_cfg "he_mu_edca_ac_vo_aci=3" "$N"
579 append base_cfg "he_mu_edca_ac_vo_ecwmin=5" "$N"
580 append base_cfg "he_mu_edca_ac_vo_ecwmax=7" "$N"
581 append base_cfg "he_mu_edca_ac_vo_timer=3" "$N"
582 fi
583
584 set_default tx_burst 2
585
586 # 802.11be
587 enable_be=0
588 case "$htmode" in
589 EHT*) enable_be=1 ;;
590 esac
591
592 if [ "$enable_be" != "0" ]; then
developer5f1d3ca2024-04-25 05:25:22 +0800593
594 json_get_vars \
595 pp_bitmap \
596 pp_mode
597
developer9198e8b2024-02-22 06:01:52 +0800598 append base_cfg "ieee80211be=1" "$N"
599 if [ "$etxbfen" -eq 0 ]; then
600 append base_cfg "eht_su_beamformee=1" "$N"
601 else
602 append base_cfg "eht_su_beamformer=1" "$N"
603 append base_cfg "eht_su_beamformee=1" "$N"
604 append base_cfg "eht_mu_beamformer=1" "$N"
605 fi
606 [ "$hwmode" = "a" ] && {
607 case $htmode in
608 EHT320*)
609 append base_cfg "eht_oper_chwidth=$eht_oper_chwidth" "$N"
610 append base_cfg "eht_oper_centr_freq_seg0_idx=$eht_oper_centr_freq_seg0_idx" "$N"
611 append base_cfg "eht_bw320_offset=$eht_bw320_offset" "$N"
612 ;;
613 *)
614 append base_cfg "eht_oper_chwidth=$vht_oper_chwidth" "$N"
615 append base_cfg "eht_oper_centr_freq_seg0_idx=$vht_center_seg0" "$N"
616 ;;
617 esac
618 }
developer5f1d3ca2024-04-25 05:25:22 +0800619
620 if [ -n "$pp_bitmap" ]; then
621 append base_cfg "punct_bitmap=$pp_bitmap" "$N"
622 fi
623
624 if [ -n "$pp_mode" ]; then
625 append base_cfg "pp_mode=$pp_mode" "$N"
626 fi
developer9198e8b2024-02-22 06:01:52 +0800627 fi
628
629 hostapd_prepare_device_config "$hostapd_conf_file" nl80211
630 cat >> "$hostapd_conf_file" <<EOF
631${channel:+channel=$channel}
632${channel_list:+chanlist=$channel_list}
633${hostapd_noscan:+noscan=1}
634${tx_burst:+tx_queue_data2_burst=$tx_burst}
635${mbssid:+mbssid=$mbssid}
636${mu_onoff:+mu_onoff=$mu_onoff}
637${rnr:+rnr=$rnr}
638${multiple_bssid:+mbssid=$multiple_bssid}
developer5cd6ced2024-03-21 15:48:34 +0800639${band_idx:+band_idx=$band_idx}
developer9198e8b2024-02-22 06:01:52 +0800640#num_global_macaddr=$num_global_macaddr
developerb537dd92024-04-22 00:51:57 +0800641#single_hw=1
developer9198e8b2024-02-22 06:01:52 +0800642$base_cfg
643
644EOF
645 json_select ..
646}
647
648mac80211_hostapd_setup_bss() {
649 local phy="$1"
650 local ifname="$2"
651 local macaddr="$3"
652 local type="$4"
653
654 hostapd_cfg=
655 append hostapd_cfg "$type=$ifname" "$N"
656
657 hostapd_set_bss_options hostapd_cfg "$phy" "$vif" || return 1
658 json_get_vars wds wds_bridge dtim_period max_listen_int start_disabled
659
660 set_default wds 0
661 set_default start_disabled 0
662
663 [ "$wds" -gt 0 ] && {
664 append hostapd_cfg "wds_sta=1" "$N"
665 [ -n "$wds_bridge" ] && append hostapd_cfg "wds_bridge=$wds_bridge" "$N"
666 }
667 [ "$start_disabled" -eq 1 ] && append hostapd_cfg "start_disabled=1" "$N"
668
669 cat >> /var/run/hostapd-$phy.conf <<EOF
670$hostapd_cfg
671bssid=$macaddr
developer9198e8b2024-02-22 06:01:52 +0800672${dtim_period:+dtim_period=$dtim_period}
673${max_listen_int:+max_listen_interval=$max_listen_int}
674EOF
675}
676
677mac80211_generate_mbssid_mac() {
678 local phy="$1"
679 local transmitted_bssid="$2"
680 local id="${mbssidx:-0}"
681
682 local ref="$(cat /sys/class/ieee80211/${phy}/macaddress)"
683
684 if [ -z "$transmitted_bssid" ]; then
685 transmitted_bssid=$ref
686 fi
687
688 if [ $id -eq 0 ]; then
689 echo "$transmitted_bssid"
690 return
691 fi
692
693 local oIFS="$IFS"; IFS=":"; set -- $transmitted_bssid; IFS="$oIFS"
694
695 # Calculate nontransmitted bssid
696 b6="0x$6"
697 ref_b6=$(($b6 % $max_mbssid))
698 b6=$(($b6 - $ref_b6 + ($ref_b6 + $id) % $max_mbssid))
699 printf "%s:%s:%s:%s:%s:%02x" $1 $2 $3 $4 $5 $b6
700}
701
702mac80211_get_addr() {
703 local phy="$1"
704 local idx="$(($2 + 1))"
705
706 head -n $idx /sys/class/ieee80211/${phy}/addresses | tail -n1
707}
708
709mac80211_generate_mac() {
710 local phy="$1"
711 local id="${macidx:-0}"
712
713 wdev_tool "$phy" get_macaddr id=$id num_global=$num_global_macaddr mbssid=${multiple_bssid:-0}
714}
715
716get_board_phy_name() (
717 local path="$1"
718 local fallback_phy=""
719
720 __check_phy() {
721 local val="$1"
722 local key="$2"
723 local ref_path="$3"
724
725 json_select "$key"
726 json_get_values path
727 json_select ..
728
729 [ "${ref_path%+*}" = "$path" ] && fallback_phy=$key
730 [ "$ref_path" = "$path" ] || return 0
731
732 echo "$key"
733 exit
734 }
735
736 json_load_file /etc/board.json
737 json_for_each_item __check_phy wlan "$path"
738 [ -n "$fallback_phy" ] && echo "${fallback_phy}.${path##*+}"
739)
740
741rename_board_phy_by_path() {
742 local path="$1"
743
744 local new_phy="$(get_board_phy_name "$path")"
745 [ -z "$new_phy" -o "$new_phy" = "$phy" ] && return
746
747 iw "$phy" set name "$new_phy" && phy="$new_phy"
748}
749
750rename_board_phy_by_name() (
751 local phy="$1"
752 local suffix="${phy##*.}"
753 [ "$suffix" = "$phy" ] && suffix=
754
755 json_load_file /etc/board.json
756 json_select wlan
757 json_select "${phy%.*}" || return 0
758 json_get_values path
759
760 prev_phy="$(iwinfo nl80211 phyname "path=$path${suffix:++$suffix}")"
761 [ -n "$prev_phy" ] || return 0
762
763 [ "$prev_phy" = "$phy" ] && return 0
764
765 iw "$prev_phy" set name "$phy"
766)
767
768find_phy() {
769 [ -n "$phy" ] && {
770 rename_board_phy_by_name "$phy"
771 [ -d /sys/class/ieee80211/$phy ] && return 0
772 }
773 [ -n "$path" ] && {
774 phy="$(iwinfo nl80211 phyname "path=$path")"
775 [ -n "$phy" ] && {
776 rename_board_phy_by_path "$path"
777 return 0
778 }
779 }
780 [ -n "$macaddr" ] && {
781 for phy in $(ls /sys/class/ieee80211 2>/dev/null); do
782 grep -i -q "$macaddr" "/sys/class/ieee80211/${phy}/macaddress" && {
783 path="$(iwinfo nl80211 path "$phy")"
784 rename_board_phy_by_path "$path"
785 return 0
786 }
787 done
788 }
789 return 1
790}
791
792mac80211_check_ap() {
793 has_ap=1
794}
795
796mac80211_set_ifname() {
797 local phy="$1"
798 local prefix="$2"
799 eval "ifname=\"$phy-$prefix\${idx_$prefix:-0}\"; idx_$prefix=\$((\${idx_$prefix:-0 } + 1))"
800}
801
802fill_mld_params() {
803 local target_mld_id=$1
804 local phy_idx=$(echo $2 | tr -d "phy")
805 local found_mld=0
806 local is_primary=1
developerb537dd92024-04-22 00:51:57 +0800807 local mld_allowed_links=0
developer9198e8b2024-02-22 06:01:52 +0800808
809 iface_list="$(cat /etc/config/wireless | grep wifi-iface | cut -d ' ' -f3 | tr -s "'\n" ' ')"
810 for iface in $iface_list
811 do
812 local mld_id="$(uci show wireless.$iface | grep "mld_id" | cut -d '=' -f2 | tr -d "'")"
813 local radio_id="$(uci show wireless.$iface | grep "device" | cut -d '=' -f2 | tr -d "radio'")"
developerb537dd92024-04-22 00:51:57 +0800814 local iface_disabled="$(uci show wireless.$iface | grep "disabled" | cut -d '=' -f2 | tr -d "'")"
815
816 if [ "$iface_disabled" != "1" ] && [ $mld_id = $target_mld_id ]; then
817 mld_allowed_links=$(($mld_allowed_links * 2 + 1))
818 [ $radio_id -lt $phy_idx ] && is_primary=0
developer9198e8b2024-02-22 06:01:52 +0800819 fi
820 done
821 json_add_string "mld_primary" $is_primary
developerb537dd92024-04-22 00:51:57 +0800822 json_add_string "mld_allowed_links" $mld_allowed_links
developer9198e8b2024-02-22 06:01:52 +0800823
824 mld_list="$(cat /etc/config/wireless | grep wifi-mld | cut -d ' ' -f3 | tr -s "'\n" ' ')"
825 for m in $mld_list
826 do
827 local mld_id="$(uci show wireless.$m | grep "mld_id" | cut -d '=' -f2 | tr -d "'")"
828 [ $mld_id = $target_mld_id ] || continue
829 found_mld=1
830
831 option_list="$(uci show wireless.$m | tr -s "\n" ' ')"
832 for option in $option_list
833 do
834 local key="$(echo $option | cut -d '.' -f3 | cut -d '=' -f1)"
835 local val="$(echo $option | cut -d '.' -f3 | cut -d '=' -f2 | tr -d "'")"
836 [ -n "$key" ] && json_add_string $key $val
837 done
838 done
839
840 if [ $found_mld -eq 0 ]; then
841 echo "mld_id $target_mld_id is not found"
842 return 1
843 fi
844 return 0
845}
846
847mac80211_prepare_vif() {
848 json_select config
849
850 json_get_vars mld_id
851 if [ -n "$mld_id" ]; then
852 fill_mld_params $mld_id $phy || return
853
854 json_get_vars mld_addr
855 if [ -z "$mld_addr" ]; then
856 json_add_string mld_addr "$(mac80211_generate_mac phy0)"
857 fi
858 fi
859
860 json_get_vars ifname mode ssid wds powersave macaddr enable wpa_psk_file vlan_file
861
862 [ -n "$ifname" ] || {
863 local prefix;
864
865 case "$mode" in
866 ap|sta|mesh) prefix=$mode;;
867 adhoc) prefix=ibss;;
868 monitor) prefix=mon;;
869 esac
870
871 mac80211_set_ifname "$phy" "$prefix"
872 }
873
874 append active_ifnames "$ifname"
875 set_default wds 0
876 set_default powersave 0
877 json_add_string _ifname "$ifname"
878
developer9198e8b2024-02-22 06:01:52 +0800879 if [ "$mbssid" -gt 0 ] && [ "$mode" == "ap" ]; then
880 [ "$mbssidx" -eq 0 ] && {
881 if [ -z $macaddr ]; then
882 transmitted_bssid="$(mac80211_generate_mac $phy)"
883 else
884 # uci set mac address
885 transmitted_bssid=$macaddr
886 fi
887 macidx="$(($macidx + 1))"
888 }
889 macaddr="$(mac80211_generate_mbssid_mac $phy $transmitted_bssid)"
890 mbssidx="$(($mbssidx + 1))"
891 elif [ -z "$macaddr" ]; then
892 macaddr="$(mac80211_generate_mac $phy)"
893 macidx="$(($macidx + 1))"
developer9198e8b2024-02-22 06:01:52 +0800894 elif [ "$macaddr" = 'random' ]; then
895 macaddr="$(macaddr_random)"
896 fi
897 json_add_string _macaddr "$macaddr"
developer9198e8b2024-02-22 06:01:52 +0800898 json_select ..
899
900
901 [ "$mode" == "ap" ] && {
902 [ -z "$wpa_psk_file" ] && hostapd_set_psk "$ifname"
903 [ -z "$vlan_file" ] && hostapd_set_vlan "$ifname"
904 }
905
906 json_select config
907
908 # It is far easier to delete and create the desired interface
909 case "$mode" in
910 ap)
911 # Hostapd will handle recreating the interface and
912 # subsequent virtual APs belonging to the same PHY
913 if [ -n "$hostapd_ctrl" ]; then
914 type=bss
915 else
916 type=interface
917 fi
918
919 mac80211_hostapd_setup_bss "$phy" "$ifname" "$macaddr" "$type" || return
920
921 [ -n "$hostapd_ctrl" ] || {
922 ap_ifname="${ifname}"
923 hostapd_ctrl="${hostapd_ctrl:-/var/run/hostapd/$ifname}"
924 }
925 ;;
926 esac
927
928 json_select ..
929}
930
931mac80211_prepare_iw_htmode() {
932 case "$htmode" in
933 VHT20|HT20|HE20) iw_htmode=HT20;;
934 HT40*|VHT40|VHT160|HE40)
935 case "$band" in
936 2g)
937 case "$htmode" in
938 HT40+) iw_htmode="HT40+";;
939 HT40-) iw_htmode="HT40-";;
940 *)
941 if [ "$channel" -lt 7 ]; then
942 iw_htmode="HT40+"
943 else
944 iw_htmode="HT40-"
945 fi
946 ;;
947 esac
948 ;;
949 *)
950 case "$(( ($channel / 4) % 2 ))" in
951 1) iw_htmode="HT40+" ;;
952 0) iw_htmode="HT40-";;
953 esac
954 ;;
955 esac
956 [ "$auto_channel" -gt 0 ] && iw_htmode="HT40+"
957 ;;
958 VHT80|HE80)
959 iw_htmode="80MHZ"
960 ;;
961 NONE|NOHT)
962 iw_htmode="NOHT"
963 ;;
964 *) iw_htmode="" ;;
965 esac
966}
967
968mac80211_add_mesh_params() {
969 for var in $MP_CONFIG_INT $MP_CONFIG_BOOL $MP_CONFIG_STRING; do
970 eval "mp_val=\"\$$var\""
971 [ -n "$mp_val" ] && json_add_string "$var" "$mp_val"
972 done
973}
974
975mac80211_setup_adhoc() {
976 local enable=$1
977 json_get_vars bssid ssid key mcast_rate
978
979 NEWUMLIST="${NEWUMLIST}$ifname "
980
981 [ "$enable" = 0 ] && {
982 ip link set dev "$ifname" down
983 return 0
984 }
985
986 keyspec=
987 [ "$auth_type" = "wep" ] && {
988 set_default key 1
989 case "$key" in
990 [1234])
991 local idx
992 for idx in 1 2 3 4; do
993 json_get_var ikey "key$idx"
994
995 [ -n "$ikey" ] && {
996 ikey="$(($idx - 1)):$(prepare_key_wep "$ikey")"
997 [ $idx -eq $key ] && ikey="d:$ikey"
998 append keyspec "$ikey"
999 }
1000 done
1001 ;;
1002 *)
1003 append keyspec "d:0:$(prepare_key_wep "$key")"
1004 ;;
1005 esac
1006 }
1007
1008 brstr=
1009 for br in $basic_rate_list; do
1010 wpa_supplicant_add_rate brstr "$br"
1011 done
1012
1013 mcval=
1014 [ -n "$mcast_rate" ] && wpa_supplicant_add_rate mcval "$mcast_rate"
1015
1016 local prev
1017 json_set_namespace wdev_uc prev
1018
1019 json_add_object "$ifname"
1020 json_add_string mode adhoc
developer5f1d3ca2024-04-25 05:25:22 +08001021 json_add_string macaddr "$macaddr"
developer9198e8b2024-02-22 06:01:52 +08001022 json_add_string ssid "$ssid"
1023 json_add_string freq "$freq"
1024 json_add_string htmode "$iw_htmode"
1025 [ -n "$bssid" ] && json_add_string bssid "$bssid"
1026 json_add_int beacon-interval "$beacon_int"
1027 [ -n "$brstr" ] && json_add_string basic-rates "$brstr"
1028 [ -n "$mcval" ] && json_add_string mcast-rate "$mcval"
1029 [ -n "$keyspec" ] && json_add_string keys "$keyspec"
1030 json_close_object
1031
1032 json_set_namespace "$prev"
1033}
1034
1035mac80211_setup_mesh() {
1036 json_get_vars ssid mesh_id mcast_rate
1037
1038 mcval=
1039 [ -n "$mcast_rate" ] && wpa_supplicant_add_rate mcval "$mcast_rate"
1040 [ -n "$mesh_id" ] && ssid="$mesh_id"
1041
1042 local prev
1043 json_set_namespace wdev_uc prev
1044
1045 json_add_object "$ifname"
1046 json_add_string mode mesh
developer5f1d3ca2024-04-25 05:25:22 +08001047 json_add_string macaddr "$macaddr"
developer9198e8b2024-02-22 06:01:52 +08001048 json_add_string ssid "$ssid"
1049 json_add_string freq "$freq"
1050 json_add_string htmode "$iw_htmode"
1051 [ -n "$mcval" ] && json_add_string mcast-rate "$mcval"
1052 json_add_int beacon-interval "$beacon_int"
1053 mac80211_add_mesh_params
1054
1055 json_close_object
1056
1057 json_set_namespace "$prev"
1058}
1059
1060mac80211_setup_monitor() {
1061 local prev
1062 json_set_namespace wdev_uc prev
1063
1064 json_add_object "$ifname"
1065 json_add_string mode monitor
1066 [ -n "$freq" ] && json_add_string freq "$freq"
1067 json_add_string htmode "$iw_htmode"
1068 json_close_object
1069
1070 json_set_namespace "$prev"
1071}
1072
1073mac80211_set_vif_txpower() {
1074 local name="$1"
1075
1076 json_select config
1077 json_get_var ifname _ifname
1078 json_get_vars vif_txpower
1079 json_select ..
1080
1081 [ -z "$vif_txpower" ] || iw dev "$ifname" set txpower fixed "${vif_txpower%%.*}00"
1082}
1083
1084wpa_supplicant_init_config() {
1085 json_set_namespace wpa_supp prev
1086
1087 json_init
1088 json_add_array config
1089
1090 json_set_namespace "$prev"
1091}
1092
1093wpa_supplicant_add_interface() {
1094 local ifname="$1"
1095 local mode="$2"
1096 local prev
1097
1098 _wpa_supplicant_common "$ifname"
1099
1100 json_set_namespace wpa_supp prev
1101
1102 json_add_object
1103 json_add_string ctrl "$_rpath"
1104 json_add_string iface "$ifname"
1105 json_add_string mode "$mode"
1106 json_add_string config "$_config"
developer5f1d3ca2024-04-25 05:25:22 +08001107 json_add_string macaddr "$macaddr"
developer9198e8b2024-02-22 06:01:52 +08001108 [ -n "$network_bridge" ] && json_add_string bridge "$network_bridge"
1109 [ -n "$wds" ] && json_add_boolean 4addr "$wds"
1110 json_add_boolean powersave "$powersave"
1111 [ "$mode" = "mesh" ] && mac80211_add_mesh_params
1112 json_close_object
1113
1114 json_set_namespace "$prev"
1115
1116 wpa_supp_init=1
1117}
1118
1119wpa_supplicant_set_config() {
1120 local phy="$1"
1121 local prev
1122
1123 json_set_namespace wpa_supp prev
1124 json_close_array
1125 json_add_string phy "$phy"
1126 json_add_boolean defer 1
1127 local data="$(json_dump)"
1128
1129 json_cleanup
1130 json_set_namespace "$prev"
1131
1132 ubus -S -t 0 wait_for wpa_supplicant || {
1133 [ -n "$wpa_supp_init" ] || return 0
1134
1135 ubus wait_for wpa_supplicant
1136 }
1137
1138 local supplicant_res="$(ubus_call wpa_supplicant config_set "$data")"
1139 ret="$?"
1140 [ "$ret" != 0 -o -z "$supplicant_res" ] && wireless_setup_vif_failed WPA_SUPPLICANT_FAILED
1141
1142 wireless_add_process "$(jsonfilter -s "$supplicant_res" -l 1 -e @.pid)" "/usr/sbin/wpa_supplicant" 1 1
1143
1144}
1145
1146hostapd_set_config() {
1147
1148 if [ "$inconsistent_country" -eq 1 ]; then
1149 echo "ERROR: Please use the same country for all the radios."
1150 wireless_setup_failed HOSTAPD_START_FAILED
1151 drv_mac80211_teardown
1152 return
1153 fi
1154
1155 [ -n "$hostapd_ctrl" ] || {
1156 ubus_call hostapd config_set '{ "phy": "'"$phy"'", "config": "", "prev_config": "'"${hostapd_conf_file}.prev"'" }' > /dev/null
1157 return 0;
1158 }
1159
1160 ubus wait_for hostapd
1161
1162 # each phy sleeps different times to prevent for ubus race condition.
1163 if [ "$phy" = "phy1" ]; then
1164 sleep 3;
1165 elif [ "$phy" = "phy2" ]; then
1166 sleep 6;
1167 fi
1168
1169 local hostapd_res="$(ubus_call hostapd config_set "{ \"phy\": \"$phy\", \"config\":\"${hostapd_conf_file}\", \"prev_config\": \"${hostapd_conf_file}.prev\"}")"
1170 ret="$?"
1171 [ "$ret" != 0 -o -z "$hostapd_res" ] && {
1172 wireless_setup_failed HOSTAPD_START_FAILED
1173 return
1174 }
1175 wireless_add_process "$(jsonfilter -s "$hostapd_res" -l 1 -e @.pid)" "/usr/sbin/hostapd" 1 1
1176}
1177
1178
1179wpa_supplicant_start() {
1180 local phy="$1"
1181
1182 [ -n "$wpa_supp_init" ] || return 0
1183
1184 ubus_call wpa_supplicant config_set '{ "phy": "'"$phy"'" }' > /dev/null
1185}
1186
1187mac80211_setup_supplicant() {
1188 local enable=$1
1189 local add_sp=0
1190
1191 wpa_supplicant_prepare_interface "$ifname" nl80211 || return 1
1192
1193 if [ "$mode" = "sta" ]; then
1194 wpa_supplicant_add_network "$ifname"
1195 else
1196 wpa_supplicant_add_network "$ifname" "$freq" "$htmode" "$hostapd_noscan"
1197 fi
1198
1199 wpa_supplicant_add_interface "$ifname" "$mode"
1200
1201 return 0
1202}
1203
1204mac80211_setup_vif() {
1205 local name="$1"
1206 local failed
1207
1208 json_select config
1209 json_get_var ifname _ifname
1210 json_get_var macaddr _macaddr
developer9198e8b2024-02-22 06:01:52 +08001211 json_get_vars mode wds powersave
1212
1213 set_default powersave 0
1214 set_default wds 0
1215
1216 case "$mode" in
1217 mesh)
1218 json_get_vars $MP_CONFIG_INT $MP_CONFIG_BOOL $MP_CONFIG_STRING
1219 wireless_vif_parse_encryption
1220 [ -z "$htmode" ] && htmode="NOHT";
1221 if wpa_supplicant -vmesh; then
1222 mac80211_setup_supplicant || failed=1
1223 else
1224 mac80211_setup_mesh
1225 fi
1226 ;;
1227 adhoc)
1228 wireless_vif_parse_encryption
1229 if [ "$wpa" -gt 0 -o "$auto_channel" -gt 0 ]; then
1230 mac80211_setup_supplicant || failed=1
1231 else
1232 mac80211_setup_adhoc
1233 fi
1234 ;;
1235 sta)
1236 mac80211_setup_supplicant || failed=1
1237 ;;
1238 monitor)
1239 mac80211_setup_monitor
1240 ;;
1241 esac
1242
1243 json_select ..
1244 [ -n "$failed" ] || wireless_add_vif "$name" "$ifname"
1245
1246 echo "Setup SMP Affinity"
1247 /sbin/smp-mt76.sh
1248}
1249
1250get_freq() {
1251 local phy="$1"
1252 local channel="$2"
1253 local band="$3"
1254
1255 case "$band" in
1256 2g) band="1:";;
1257 5g) band="2:";;
1258 60g) band="3:";;
1259 6g) band="4:";;
1260 esac
1261
1262 iw "$phy" info | awk -v band="$band" -v channel="[$channel]" '
1263
1264$1 ~ /Band/ {
1265 band_match = band == $2
1266}
1267
1268band_match && $3 == "MHz" && $4 == channel {
1269 print $2
1270 exit
1271}
1272'
1273}
1274
1275chan_is_dfs() {
1276 local phy="$1"
1277 local chan="$2"
1278 iw "$phy" info | grep -E -m1 "(\* ${chan:-....} MHz${chan:+|\\[$chan\\]})" | grep -q "MHz.*radar detection"
1279 return $!
1280}
1281
1282mac80211_set_noscan() {
1283 hostapd_noscan=1
1284}
1285
1286drv_mac80211_cleanup() {
1287 hostapd_common_cleanup
1288}
1289
1290mac80211_reset_config() {
1291 local phy="$1"
1292
1293 hostapd_conf_file="/var/run/hostapd-$phy.conf"
1294 ubus_call hostapd config_set '{ "phy": "'"$phy"'", "config": "", "prev_config": "'"$hostapd_conf_file"'" }' > /dev/null
1295 ubus_call wpa_supplicant config_set '{ "phy": "'"$phy"'", "config": [] }' > /dev/null
1296 wdev_tool "$phy" set_config '{}'
1297}
1298
1299mac80211_count_ap() {
1300 total_num_ap=$(($total_num_ap + 1))
1301}
1302
1303country_consistent_check() {
1304 local i
1305 inconsistent_country=0
1306 country_list="$(cat /etc/config/wireless | grep country | cut -d ' ' -f3 | tr -s "'\n" ' ')"
1307 for i in $country_list
1308 do
1309 ret="$(echo $country_list | awk '{print ($2 == "" || $1 == $2)}')"
1310 [ $ret = '0' ] && {
1311 inconsistent_country=1
1312 return
1313 }
1314 country_list="$(echo $country_list | sed -r 's/[A-Z]{2}( )*//')"
1315 done
1316}
1317
1318drv_mac80211_setup() {
1319 json_select config
1320 json_get_vars \
1321 phy macaddr path \
1322 country chanbw distance \
1323 txpower \
1324 rxantenna txantenna \
1325 frag rts beacon_int:100 htmode \
1326 num_global_macaddr:1 multiple_bssid \
1327 sr_enable sr_enhanced
1328 json_get_values basic_rate_list basic_rate
1329 json_get_values scan_list scan_list
1330 json_select ..
1331
1332 json_select data && {
1333 json_get_var prev_rxantenna rxantenna
1334 json_get_var prev_txantenna txantenna
1335 json_select ..
1336 }
1337
1338 find_phy || {
1339 echo "Could not find PHY for device '$1'"
1340 wireless_set_retry 0
1341 return 1
1342 }
1343
1344 local wdev
1345 local cwdev
1346 local found
1347
1348 # convert channel to frequency
1349 [ "$auto_channel" -gt 0 ] || freq="$(get_freq "$phy" "$channel" "$band")"
1350
1351 [ -n "$country" ] && {
1352 iw reg get | grep -q "^country $country:" || {
1353 iw reg set "$country"
1354 sleep 1
1355 }
1356 }
1357
1358 hostapd_conf_file="/var/run/hostapd-$phy.conf"
1359
1360 macidx=0
1361 staidx=0
1362 mbssidx=0
1363
developer5f1d3ca2024-04-25 05:25:22 +08001364 if [ "$phy" = "phy1" ]; then
1365 macidx=20;
1366 elif [ "$phy" = "phy2" ]; then
1367 macidx=40;
1368 fi
1369
developer9198e8b2024-02-22 06:01:52 +08001370 [ -n "$chanbw" ] && {
1371 for file in /sys/kernel/debug/ieee80211/$phy/ath9k*/chanbw /sys/kernel/debug/ieee80211/$phy/ath5k/bwmode; do
1372 [ -f "$file" ] && echo "$chanbw" > "$file"
1373 done
1374 }
1375
1376 set_default rxantenna 0xffffffff
1377 set_default txantenna 0xffffffff
1378 set_default distance 0
1379
1380 [ "$txantenna" = "all" ] && txantenna=0xffffffff
1381 [ "$rxantenna" = "all" ] && rxantenna=0xffffffff
1382
1383 [ "$rxantenna" = "$prev_rxantenna" -a "$txantenna" = "$prev_txantenna" ] || mac80211_reset_config "$phy"
1384 wireless_set_data phy="$phy" txantenna="$txantenna" rxantenna="$rxantenna"
1385
1386 iw phy "$phy" set antenna $txantenna $rxantenna >/dev/null 2>&1
1387 iw phy "$phy" set distance "$distance" >/dev/null 2>&1
1388
1389 if [ -n "$txpower" ]; then
1390 iw phy "$phy" set txpower fixed "${txpower%%.*}00"
1391 else
1392 iw phy "$phy" set txpower auto
1393 fi
1394
1395 [ -n "$frag" ] && iw phy "$phy" set frag "${frag%%.*}"
1396 [ -n "$rts" ] && iw phy "$phy" set rts "${rts%%.*}"
1397
1398 has_ap=
1399 hostapd_ctrl=
1400 ap_ifname=
1401 hostapd_noscan=
1402 wpa_supp_init=
1403 for_each_interface "ap" mac80211_check_ap
1404
1405 [ -f "$hostapd_conf_file" ] && mv "$hostapd_conf_file" "$hostapd_conf_file.prev"
1406
1407 for_each_interface "sta adhoc mesh" mac80211_set_noscan
1408 [ -n "$has_ap" ] && mac80211_hostapd_setup_base "$phy"
1409
1410 local prev
1411 json_set_namespace wdev_uc prev
1412 json_init
1413 json_set_namespace "$prev"
1414
1415 wpa_supplicant_init_config
1416
1417 total_num_ap=0
1418 max_mbssid=1
1419 for_each_interface "ap" mac80211_count_ap
1420 total_num_ap=$(($total_num_ap - 1))
1421 while [ $total_num_ap -gt 0 ]
1422 do
1423 total_num_ap=$(($total_num_ap >> 1))
1424 max_mbssid=$(($max_mbssid << 1))
1425 done
1426
1427 mac80211_prepare_iw_htmode
1428 active_ifnames=
1429 for_each_interface "ap sta adhoc mesh monitor" mac80211_prepare_vif
1430 for_each_interface "ap sta adhoc mesh monitor" mac80211_setup_vif
1431
1432 country_consistent_check
1433
1434 [ -x /usr/sbin/wpa_supplicant ] && wpa_supplicant_set_config "$phy"
1435 [ -x /usr/sbin/hostapd ] && hostapd_set_config "$phy"
1436
1437 [ -n "$sr_enable" ] && echo "$sr_enable" > /sys/kernel/debug/ieee80211/$phy/mt76/sr_enable
1438 [ -n "$sr_enhanced" ] && echo "$sr_enhanced" > /sys/kernel/debug/ieee80211/$phy/mt76/sr_enhanced_enable
1439
1440 [ -x /usr/sbin/wpa_supplicant ] && wpa_supplicant_start "$phy"
1441
1442 json_set_namespace wdev_uc prev
1443 wdev_tool "$phy" set_config "$(json_dump)" $active_ifnames
1444 json_set_namespace "$prev"
1445
1446 for_each_interface "ap sta adhoc mesh monitor" mac80211_set_vif_txpower
1447 wireless_set_up
developerb537dd92024-04-22 00:51:57 +08001448
1449 echo /tmp/%e.core > /proc/sys/kernel/core_pattern
developer9198e8b2024-02-22 06:01:52 +08001450}
1451
1452_list_phy_interfaces() {
1453 local phy="$1"
1454 if [ -d "/sys/class/ieee80211/${phy}/device/net" ]; then
1455 ls "/sys/class/ieee80211/${phy}/device/net" 2>/dev/null;
1456 else
1457 ls "/sys/class/ieee80211/${phy}/device" 2>/dev/null | grep net: | sed -e 's,net:,,g'
1458 fi
1459}
1460
1461list_phy_interfaces() {
1462 local phy="$1"
1463
1464 for dev in $(_list_phy_interfaces "$phy"); do
1465 readlink "/sys/class/net/${dev}/phy80211" | grep -q "/${phy}\$" || continue
1466 echo "$dev"
1467 done
1468}
1469
1470drv_mac80211_teardown() {
1471 json_select data
1472 json_get_vars phy
1473 json_select ..
1474 [ -n "$phy" ] || {
1475 echo "Bug: PHY is undefined for device '$1'"
1476 return 1
1477 }
1478
developerb537dd92024-04-22 00:51:57 +08001479 # each phy sleeps different times to prevent for ubus race condition.
1480 if [ "$phy" = "phy1" ]; then
1481 sleep 3;
1482 elif [ "$phy" = "phy0" ]; then
1483 sleep 6;
1484 fi
1485
developer9198e8b2024-02-22 06:01:52 +08001486 mac80211_reset_config "$phy"
1487
1488 for wdev in $(list_phy_interfaces "$phy"); do
1489 ip link set dev "$wdev" down
1490 iw dev "$wdev" del
1491 done
1492}
1493
1494add_driver mac80211