Show pagesourceOld revisionsBacklinksBack to top × Table of Contents Wi-Fi automatic channel selection with iwchan Introduction Instructions Examples Automated Wi-Fi automatic channel selection with iwchan This article relies on the following: Accessing web interface / command-line interface Managing configs / packages / services / logs 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 ACS algorithm does not work well with your hardware/driver. Instructions 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() } } } 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 Examples # 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 Automated 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 This website uses cookies. By using the website, you agree with storing cookies on your computer. Also you acknowledge that you have read and understand our Privacy Policy. If you do not agree leave the website.OKMore information about cookies Last modified: 2023/01/16 23:24by vgaetera