Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
docs:guide-user:network:wifi:iwchan [2023/01/17 04:24] – [Wi-Fi automatic channel selection with iwchan] update infobox vgaeteradocs:guide-user:network:wifi:iwchan [2023/09/08 22:57] (current) – deprecated in favor of the default ACS algorithm: https://forum.openwrt.org/t/wi-fi-channel-auto-selection/47776/8 vgaetera
Line 1: Line 1:
-====== Wi-Fi automatic channel selection with iwchan ====== 
-{{section>meta:infobox:howto_links#basic_skills&noheader&nofooter&noeditbutton}} 
- 
-===== Introduction ===== 
-  * This instruction provides a method to automatically select a wireless channel. 
-  * It calculates the load to frequency distribution and selects the channel with the least load. 
-  * The threshold frequency and load parameters help to minimize excessive channel change. 
-  * You can use this in case the [[https://forum.openwrt.org/t/wi-fi-channel-auto-selection/47776/8|ACS algorithm]] does not work well with your hardware/driver. 
- 
-===== Instructions ===== 
-<code awk iwchan.awk> 
-#!/usr/bin/awk -f 
- 
-# Coded by: Vladislav Grigoryev <vg[dot]aetera[at]gmail[dot]com> 
-# License: GNU General Public License (GPL) version 3+ 
-# Description: Select wireless channel automatically 
- 
-function get_iwphy() { 
- cmd = "iw phy" 
- while(cmd | getline) { 
- if($0 ~ /^\s*Wiphy\s/) 
- phy = gensub(/^\s*\w*\s(\w+)$/, "\\1", 1, $0) 
- else if($0 ~ /^\s*Band\s/) 
- band = gensub(/^\s*\w*\s([0-9]+):$/, "\\1", 1, $0) 
- else if($0 ~ /^\s*\*\s*[0-9]+\s*MHz.*dBm/) { 
- freq = gensub(/^.*\s([0-9]+)\s*MHz.*$/, "\\1", 1, $0) 
- chan = gensub(/^.*\[([0-9]+)\].*$/, "\\1", 1, $0) 
- iwphy[phy, freq, "band"] = band 
- iwphy[phy, freq, "chan"] = chan 
- } 
- } 
- close(cmd) 
-} 
- 
-function get_iwdev() { 
- cmd = "iw dev" 
- while(cmd | getline) { 
- if($0 ~ /^\s*phy\x23/) 
- phy = gensub(/^\s*(\w+)\x23([0-9]+)$/, "\\1\\2", 1, $0) 
- else if($0 ~ /^\s*Interface\s/) 
- dev = gensub(/^\s*\w*\s(\w+)$/, "\\1", 1, $0) 
- else if($0 ~ /^\s*channel\s/) { 
- freq = gensub(/^.*\(([0-9]+)\s*MHz\).*$/, "\\1", 1, $0) 
- iwdev[phy, dev, "freq"] = freq 
- } 
- } 
- close(cmd) 
-} 
- 
-function get_iwconf() { 
- for(iwdev_subs in iwdev) { 
- split(iwdev_subs, iwdev_sub, SUBSEP) 
- if(iwdev_sub[3] != "freq") continue 
- phy = iwdev_sub[1] 
- dev = iwdev_sub[2] 
- if(phy_conf == "") phy_conf = phy 
- if(phy_conf != phy) continue 
- dev_conf = dev 
- freq_conf = iwdev[phy_conf, dev_conf, "freq"] 
- band_conf = iwphy[phy_conf, freq_conf, "band"] 
- } 
-} 
- 
-function get_iwscan() { 
- cmd = "iw dev "dev_conf" scan" 
- while(cmd | getline) { 
- if($0 ~ /^\s*BSS\s/) 
- bssid = gensub(/^\s*\w*\s*([:0-9a-f]+).*$/, "\\1", 1, $0) 
- else if($0 ~ /^\s*freq:/) { 
- freq = gensub(/^\s*\w*:\s*([0-9]+).*$/, "\\1", 1, $0) 
- iwscan[bssid, "freq"] = freq 
- } 
- else if($0 ~ /^\s*signal:/) { 
- signal = gensub(/^\s*\w*:\s*([-.0-9]+).*$/, "\\1", 1, $0) + 0 
- iwscan[bssid, "signal"] = signal 
- if(signal < - 100) quality = 0 
- else if(signal < - 50) quality = 2 * (signal + 100) 
- else quality = 100 
- iwscan[bssid, "quality"] = quality 
- } 
- else if($0 ~ /^\s*SSID:/) { 
- ssid = gensub(/^\s*\w*:\s*(.*)$/, "\\1", 1, $0) 
- iwscan[bssid, "ssid"] = ssid 
- } 
- } 
- close(cmd) 
-} 
- 
-function get_iwload() { 
- for(iwphy_subs in iwphy) { 
- split(iwphy_subs, iwphy_sub, SUBSEP) 
- if(iwphy_sub[3] != "chan") continue 
- phy = iwphy_sub[1] 
- freq = iwphy_sub[2] 
- band = iwphy[phy, freq, "band"] 
- load = iwphy[phy, freq, "load"] 
- if(band != band_conf) continue 
- for(iwscan_subs in iwscan) { 
- split(iwscan_subs, iwscan_sub, SUBSEP) 
- if(iwscan_sub[2] != "freq") continue 
- bssid = iwscan_sub[1] 
- freq_bssid = iwscan[bssid, "freq"] 
- signal = iwscan[bssid, "signal"] 
- freq_diff = freq - freq_bssid 
- if(freq_diff < 0) freq_diff = - freq_diff 
- if(freq_diff < 5) signal_factor = 100 
- else if(freq_diff < 10) signal_factor = 95 
- else if(freq_diff < 15) signal_factor = 85 
- else if(freq_diff < 20) signal_factor = 15 
- else if(freq_diff < 25) signal_factor = 5 
- else signal_factor = 0 
- if(signal < - 100) load += 0 
- else load += (signal + 100) * signal_factor 
- iwphy[phy, freq, "load"] = load 
- } 
- } 
-} 
- 
-function get_iwstatus() { 
- for(iwphy_subs in iwphy) { 
- split(iwphy_subs, iwphy_sub, SUBSEP) 
- if(iwphy_sub[3] != "chan") continue 
- phy = iwphy_sub[1] 
- freq = iwphy_sub[2] 
- band = iwphy[phy, freq, "band"] 
- load = iwphy[phy, freq, "load"] 
- if(band != band_conf) continue 
- if(load_optim != "" && load_optim < load) continue 
- freq_optim = freq 
- load_optim = load 
- } 
- status_conf = "-" 
- iwphy[phy_conf, freq_conf, "status"] = status_conf 
- status_optim = iwphy[phy_conf, freq_optim, "status"] "+" 
- iwphy[phy_conf, freq_optim, "status"] = status_optim 
-} 
- 
-function get_iwchan() { 
- freq_diff = freq_conf - freq_optim 
- load_conf = iwphy[phy_conf, freq_conf, "load"] 
- load_optim = iwphy[phy_conf, freq_optim, "load"] 
- load_diff = load_conf - load_optim 
- if(freq_diff < 0) freq_diff = - freq_diff 
- if(freq_diff < freq_thr || load_diff < load_thr) return 
- chan_optim = iwphy[phy_conf, freq_optim, "chan"] 
- printf "%d\n", chan_optim 
-} 
- 
-function print_iwinfo() { 
- printf "Phy:\t%s\nDev:\t%s\nBand:\t%s\nFreqTh:\t%d\nLoadTh:\t%d\n", 
- phy_conf, dev_conf, band_conf, freq_thr, load_thr 
-} 
- 
-function print_iwscan() { 
- cmd = "sort -n" 
- printf "\nFreq\tChannel\tSignal\tQuality\tBSSID\t\t\tSSID\n" 
- for(iwscan_subs in iwscan) { 
- split(iwscan_subs, iwscan_sub, SUBSEP) 
- if(iwscan_sub[2] != "ssid") continue 
- bssid = iwscan_sub[1] 
- freq = iwscan[bssid, "freq"] 
- chan = iwphy[phy_conf, freq, "chan"] 
- signal = iwscan[bssid, "signal"] 
- quality = iwscan[bssid, "quality"] 
- ssid = iwscan[bssid, "ssid"] 
- printf "%d\t%d\t%d\t%d\t%s\t%s\n", freq, chan, signal, quality, 
- bssid, ssid | cmd 
- } 
- close(cmd) 
-} 
- 
-function print_iwlist() { 
- cmd = "sort -n" 
- printf "\nFreq\tChannel\tLoad\tStatus\n" 
- for(iwphy_subs in iwphy) { 
- split(iwphy_subs, iwphy_sub, SUBSEP) 
- if(iwphy_sub[3] != "chan") continue 
- phy = iwphy_sub[1] 
- freq = iwphy_sub[2] 
- band = iwphy[phy, freq, "band"] 
- chan = iwphy[phy, freq, "chan"] 
- load = iwphy[phy, freq, "load"] 
- status = iwphy[phy, freq, "status"] 
- if(band != band_conf) continue 
- printf "%d\t%d\t%d\t%s\n", freq, chan, load, status | cmd 
- } 
- close(cmd) 
-} 
- 
-BEGIN { 
- subcmd = ARGV[1] 
- phy_conf = ARGV[2] 
- freq_thr = ARGV[3] 
- load_thr = ARGV[4] 
- if(subcmd == "") subcmd = "help" 
- if(freq_thr == "") freq_thr = 15 
- if(load_thr == "") load_thr = 1000 
- if(subcmd == "help") 
- printf "awk -f iwchan.awk [show|get|help] [phy] [freq_thr] [load_thr]\n" 
- else if(subcmd == "get" || subcmd == "show") { 
- get_iwphy() 
- get_iwdev() 
- get_iwconf() 
- get_iwscan() 
- get_iwload() 
- get_iwstatus() 
- if(subcmd == "get") get_iwchan() 
- else if(subcmd == "show") { 
- print_iwinfo() 
- print_iwscan() 
- print_iwlist() 
- } 
- } 
-} 
-</code> 
- 
-<code bash iwchan.sh> 
-# Description: OpenWrt iwchan wrapper script 
- 
-IWCHAN="${0%.*}.awk" 
-PHYID="${1:-0}" 
-CHAN="$(awk -f "${IWCHAN}" get "phy${PHYID}" 2> /dev/null)" 
- 
-if [ -z "${CHAN}" ]; then exit 0; fi 
-uci set wireless."radio${PHYID}".channel="${CHAN}" 
-wifi reload 
-</code> 
- 
-===== Examples ===== 
-<code bash> 
-# awk -f iwchan.awk help 
-awk -f iwchan.awk [show|get|help] [phy] [freq_thr] [load_thr] 
- 
-# awk -f iwchan.awk get 
-5 
- 
-# awk -f iwchan.awk show 
-Phy: phy0 
-Dev: wlp2s0 
-Band: 1 
-FreqTh: 15 
-LoadTh: 1000 
- 
-Freq Channel Signal Quality BSSID SSID 
-2412 1 -63 74 90:94:e4:ef:0c:66 vghome 
-2412 1 -74 52 10:fe:ed:2a:1f:cc Dead Moroz-z-z 
-2437 6 -72 56 c4:6e:1f:65:65:02 TP-LINK_656502 
-2457 10 -65 70 d8:0d:17:21:ff:a6 TP-Link_FFA6 
-2457 10 -83 34 c4:6e:1f:70:ed:6e TP-LINK_ED6E 
-2462 11 -57 86 c0:25:e9:c4:b8:68 CityLink-12 
-2467 12 -58 84 54:04:a6:c7:34:ac quick3 
- 
-Freq Channel Load Status 
-2412 1 6300 - 
-2417 2 6125  
-2422 3 5775  
-2427 4 3325  
-2432 5 2975 + 
-2437 6 3060  
-2442 7 3655  
-2447 8 7655  
-2452 9 9645  
-2457 10 12995  
-2462 11 13230  
-2467 12 12705  
-2472 13 8425  
-</code> 
- 
-===== Automated ===== 
-<code bash> 
-URL="https://openwrt.org/_export/code/docs/guide-user/network/wifi/iwchan" 
-uclient-fetch -O /root/iwchan.awk "${URL}?codeblock=0" 
-uclient-fetch -O /root/iwchan.sh "${URL}?codeblock=1" 
-cat << EOF >> /etc/sysupgrade.conf 
-/root 
-EOF 
-cat << "EOF" >> /etc/crontabs/root 
-0 4 * * * . /root/iwchan.sh 
-EOF 
-/etc/init.d/cron restart 
-</code> 
  
  • Last modified: 2023/01/17 04:24
  • by vgaetera