wifi: Introduce 802.11ac support
authorFelix Fietkau <nbd@openwrt.org>
Mon, 3 Feb 2014 13:31:44 +0000 (13:31 +0000)
committerFelix Fietkau <nbd@openwrt.org>
Mon, 3 Feb 2014 13:31:44 +0000 (13:31 +0000)
This patch introduces 802.11ac support to mac80211 and hostapd. The split of
VHT160 in two 80 MHz bands is not yet supported, since it requires an
additional user supplied parameter for the channel of the second band.

Signed-off-by: Matti Laakso <malaakso@elisanet.fi>
Signed-off-by: Simon Wunderlich <simon@open-mesh.com>
[sven@open-mesh.com: Rebased patch, merged htmode and vhtmode,
removed special hwmode, replaced uci vht_capab list with overwritable
autoconfig, fixed hostapd integration, fixed commit description, add HT40+/-
for VHT modes, add VHT40 center_freq autoconfig, refactored major parts]
Signed-off-by: Sven Eckelmann <sven@open-mesh.com>
SVN-Revision: 39456

package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh
package/kernel/mac80211/files/lib/wifi/mac80211.sh
package/network/services/hostapd/files/hostapd-full.config
package/network/services/hostapd/files/hostapd-mini.config

index c98807f3cf2bd65e23b0b7362c716e99c4029cc3..52e58beb519ebf0e316e1916d86fe1ebe92c32c9 100644 (file)
@@ -23,6 +23,20 @@ drv_mac80211_init_device_config() {
        config_add_int rxantenna txantenna antenna_gain txpower distance
        config_add_boolean noscan
        config_add_array ht_capab
+       config_add_boolean \
+               rxldpc \
+               short_gi_80 \
+               short_gi_160 \
+               tx_stbc_2by1 \
+               su_beamformer \
+               su_beamformee \
+               mu_beamformer \
+               mu_beamformee \
+               vht_txop_ps \
+               htc_vht \
+               rx_antenna_pattern \
+               tx_antenna_pattern
+       config_add_int vht_max_mpdu vht_max_rx_stbc vht_link_adapt vht160
 }
 
 drv_mac80211_init_iface_config() {
@@ -55,12 +69,164 @@ mac80211_hostapd_setup_base() {
                append base_cfg "ieee80211n=1" "$N"
 
                ht_capab=
-               [ -n "$htmode" ] && ht_capab="[$htmode]"
+               case "$htmode" in
+                       HT20|HT40-|HT40+) ht_capab="[$htmode]";;
+                       VHT40|VHT80|VHT160)
+                               case "$channel" in
+                                       36|44|52|60|100|108|116|124|132|140|149|157) ht_capab="[HT40+]";;
+                                       40|48|56|64|104|112|120|128|136|144|153|161) ht_capab="[HT40-]";;
+                               esac
+                               ;;
+               esac
                for cap in $ht_capab_list; do
                        ht_capab="$ht_capab[$cap]"
                done
 
                [ -n "$ht_capab" ] && append base_cfg "ht_capab=$ht_capab" "$N"
+
+               # 802.11ac
+               enable_ac=0
+               idx="$channel"
+               case "$htmode" in
+                       VHT40)
+                               case "$channel" in
+                                       36|40) idx=38;;
+                                       44|48) idx=42;;
+                                       52|56) idx=54;;
+                                       60|64) idx=58;;
+                                       100|104) idx=102;;
+                                       108|112) idx=110;;
+                                       116|120) idx=118;;
+                                       124|128) idx=126;;
+                                       132|136) idx=134;;
+                                       140|144) idx=142;;
+                                       149|153) idx=151;;
+                                       157|161) idx=159;;
+                               esac
+                               enable_ac=1
+                               append base_cfg "vht_oper_chwidth=0" "$N"
+                               append base_cfg "vht_oper_centr_freq_seg0_idx=$idx" "$N"
+                       ;;
+                       VHT80)
+                               case "$channel" in
+                                       36|40|44|48) idx=42;;
+                                       52|56|60|64) idx=58;;
+                                       100|104|108|112) idx=106;;
+                                       116|120|124|128) idx=122;;
+                                       132|136|140|144) idx=138;;
+                                       149|153|157|161) idx=155;;
+                               esac
+                               enable_ac=1
+                               append base_cfg "vht_oper_chwidth=1" "$N"
+                               append base_cfg "vht_oper_centr_freq_seg0_idx=$idx" "$N"
+                       ;;
+                       VHT160)
+                               case "$channel" in
+                                       36|40|44|48|52|56|60|64) idx=50;;
+                                       100|104|108|112|116|120|124|128) idx=114;;
+                               esac
+                               enable_ac=1
+                               append base_cfg "vht_oper_chwidth=2" "$N"
+                               append base_cfg "vht_oper_centr_freq_seg0_idx=$idx" "$N"
+                       ;;
+               esac
+
+               if [ "$enable_ac" != "0" ]; then
+                       json_get_vars \
+                               rxldpc:1 \
+                               short_gi_80:1 \
+                               short_gi_160:1 \
+                               tx_stbc_2by1:1 \
+                               su_beamformer:1 \
+                               su_beamformee:1 \
+                               mu_beamformer:1 \
+                               mu_beamformee:1 \
+                               vht_txop_ps:1 \
+                               htc_vht:1 \
+                               rx_antenna_pattern:1 \
+                               tx_antenna_pattern:1 \
+                               vht_max_mpdu:11454 \
+                               vht_max_rx_stbc:4 \
+                               vht_link_adapt:3 \
+                               vht160:2
+
+                       append base_cfg "ieee80211ac=1" "$N"
+                       vht_capab=""
+                       vht_cap=0
+                       for cap in $(iw phy "$phy" info | awk -F "[()]" '/VHT Capabilities/ { print $2 }'); do
+                               vht_cap="$(($vht_cap | $cap))"
+                       done
+
+                       # boolean
+                       [ "$((($vht_cap & 16) * $rxldpc))" -eq 16 ] && \
+                               vht_capab="$vht_capab[RXLDPC]"
+                       [ "$((($vht_cap & 32) * $short_gi_80))" -eq 32 ] && \
+                               vht_capab="$vht_capab[SHORT-GI-80]"
+                       [ "$((($vht_cap & 64) * $short_gi_160))" -eq 64 ] && \
+                               vht_capab="$vht_capab[SHORT-GI-160]"
+                       [ "$((($vht_cap & 128) * $tx_stbc_2by1))" -eq 128 ] && \
+                               vht_capab="$vht_capab[TX-STBC-2BY1]"
+                       [ "$((($vht_cap & 2048) * $su_beamformer))" -eq 2048 ] && \
+                               vht_capab="$vht_capab[SU-BEAMFORMER]"
+                       [ "$((($vht_cap & 4096) * $su_beamformee))" -eq 4096 ] && \
+                               vht_capab="$vht_capab[SU-BEAMFORMEE]"
+                       [ "$((($vht_cap & 524288) * $mu_beamformer))" -eq 524288 ] && \
+                               vht_capab="$vht_capab[MU-BEAMFORMER]"
+                       [ "$((($vht_cap & 1048576) * $mu_beamformee))" -eq 1048576 ] && \
+                               vht_capab="$vht_capab[MU-BEAMFORMEE]"
+                       [ "$((($vht_cap & 2097152) * $vht_txop_ps))" -eq 2097152 ] && \
+                               vht_capab="$vht_capab[VHT-TXOP-PS]"
+                       [ "$((($vht_cap & 4194304) * $htc_vht))" -eq 4194304 ] && \
+                               vht_capab="$vht_capab[HTC-VHT]"
+                       [ "$((($vht_cap & 268435456) * $rx_antenna_pattern))" -eq 268435456 ] && \
+                               vht_capab="$vht_capab[RX-ANTENNA-PATTERN]"
+                       [ "$((($vht_cap & 536870912) * $tx_antenna_pattern))" -eq 536870912 ] && \
+                               vht_capab="$vht_capab[TX-ANTENNA-PATTERN]"
+
+                       # supported Channel widths
+                       vht160_hw=0
+                       [ "$(($vht_cap & 12))" -eq 4 -a 1 -le "$vht160" ] && \
+                               vht160_hw=1
+                       [ "$(($vht_cap & 12))" -eq 8 -a 2 -le "$vht160" ] && \
+                               vht160_hw=2
+                       [ "$vht160_hw" = 1 ] && vht_capab="$vht_capab[VHT160]"
+                       [ "$vht160_hw" = 2 ] && vht_capab="$vht_capab[VHT160-80PLUS80]"
+
+                       # maximum MPDU length
+                       vht_max_mpdu_hw=3895
+                       [ "$(($vht_cap & 3))" -ge 1 -a 7991 -le "$vht_max_mpdu" ] && \
+                               vht_max_mpdu_hw=7991
+                       [ "$(($vht_cap & 3))" -ge 2 -a 11454 -le "$vht_max_mpdu" ] && \
+                               vht_max_mpdu_hw=11454
+                       [ "$vht_max_mpdu_hw" != 3895 ] && \
+                               vht_capab="$vht_capab[MAX-MPDU-$vht_max_mpdu_hw]"
+
+                       # support for the reception of PPDUs using STBC
+                       vht_max_rx_stbc_hw=0
+                       [ "$(($vht_cap & 1792))" -ge 256 -a 1 -le "$vht_max_rx_stbc" ] && \
+                               vht_max_rx_stbc_hw=1
+                       [ "$(($vht_cap & 1792))" -ge 512 -a 2 -le "$vht_max_rx_stbc" ] && \
+                               vht_max_rx_stbc_hw=2
+                       [ "$(($vht_cap & 1792))" -ge 768 -a 3 -le "$vht_max_rx_stbc" ] && \
+                               vht_max_rx_stbc_hw=3
+                       [ "$(($vht_cap & 1792))" -ge 1024 -a 4 -le "$vht_max_rx_stbc" ] && \
+                               vht_max_rx_stbc_hw=4
+                       [ "$vht_max_rx_stbc_hw" = 1 ] && vht_capab="$vht_capab[RX-STBC-1]"
+                       [ "$vht_max_rx_stbc_hw" = 2 ] && vht_capab="$vht_capab[RX-STBC-12]"
+                       [ "$vht_max_rx_stbc_hw" = 3 ] && vht_capab="$vht_capab[RX-STBC-123]"
+                       [ "$vht_max_rx_stbc_hw" = 4 ] && vht_capab="$vht_capab[RX-STBC-1234]"
+
+                       # whether or not the STA supports link adaptation using VHT variant
+                       vht_link_adapt_hw=0
+                       [ "$(($vht_cap & 201326592))" -ge 134217728 -a 2 -le "$vht_link_adapt" ] && \
+                               vht_link_adapt_hw=2
+                       [ "$(($vht_cap & 201326592))" -ge 201326592 -a 3 -le "$vht_link_adapt" ] && \
+                               vht_link_adapt_hw=3
+                       [ "$vht_link_adapt_hw" != 0 ] && \
+                               vht_capab="$vht_capab[VHT-LINK-ADAPT-$vht_link_adapt_hw]"
+
+                       [ -n "$vht_capab" ] && append base_cfg "vht_capab=$vht_capab" "$N"
+               fi
        }
 
        hostapd_prepare_device_config "$hostapd_conf_file" nl80211
index e33b09abb2b3f84fc83d542873b921012c93fc74..e299ab939fdd8543d81d9da3420b096179ee3349 100644 (file)
@@ -69,6 +69,8 @@ detect_mac80211() {
                mode_11n=""
                mode_band="g"
                channel="11"
+               htmode=""
+
                ht_cap=0
                for cap in $(iw phy "$dev" info | grep 'Capabilities:' | cut -d: -f2); do
                        ht_cap="$(($ht_cap | $cap))"
@@ -76,7 +78,7 @@ detect_mac80211() {
                ht_capab="";
                [ "$ht_cap" -gt 0 ] && {
                        mode_11n="n"
-                       append ht_capab "       option htmode   HT20" "$N"
+                       htmode="HT20"
 
                        list="  list ht_capab"
                        [ "$(($ht_cap & 1))" -eq 1 ] && append ht_capab "$list  LDPC" "$N"
@@ -91,6 +93,15 @@ detect_mac80211() {
                }
                iw phy "$dev" info | grep -q '2412 MHz' || { mode_band="a"; channel="36"; }
 
+               vht_cap=$(iw phy "$dev" info | grep -c 'VHT Capabilities')
+               [ "$vht_cap" -gt 0 ] && {
+                       mode_band="a";
+                       channel="36"
+                       htmode="VHT80"
+               }
+
+               [ -n $htmode ] && append ht_capab "     option htmode   $htmode" "$N"
+
                if [ -x /usr/bin/readlink ]; then
                        path="$(readlink -f /sys/class/ieee80211/${dev}/device)"
                        path="${path##/sys/devices/}"
index bc999c04a1e895a1b68d3de3bcc626eea49b3bb0..e021cd005807443d2fd98c1605c8888b2d3fbb8a 100644 (file)
@@ -139,6 +139,9 @@ CONFIG_IEEE80211R=y
 # IEEE 802.11n (High Throughput) support
 CONFIG_IEEE80211N=y
 
+# IEEE 802.11ac (Very High Throughput) support
+CONFIG_IEEE80211AC=y
+
 # Remove debugging code that is printing out debug messages to stdout.
 # This can be used to reduce the size of the hostapd considerably if debugging
 # code is not needed.
index 01a04cb237e667b097c076995586667c75b9a889..367570993586cab632535988aa8644610bc4204f 100644 (file)
@@ -138,6 +138,9 @@ CONFIG_PEERKEY=y
 # IEEE 802.11n (High Throughput) support
 CONFIG_IEEE80211N=y
 
+# IEEE 802.11ac (Very High Throughput) support
+CONFIG_IEEE80211AC=y
+
 # Remove debugging code that is printing out debug messages to stdout.
 # This can be used to reduce the size of the hostapd considerably if debugging
 # code is not needed.