mac80211: TDLS: add proper HT-oper IE
authorArik Nemtsov <arik@wizery.com>
Sun, 25 Oct 2015 08:59:34 +0000 (10:59 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Tue, 3 Nov 2015 09:42:47 +0000 (10:42 +0100)
When 11n peers performs a TDLS connection on a legacy BSS, the HT
operation IE must be specified according to IEEE802.11-2012 section
9.23.3.2. Otherwise HT-protection is compromised and the medium becomes
noisy for both the TDLS and the BSS links.

Signed-off-by: Arik Nemtsov <arikx.nemtsov@intel.com>
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
net/mac80211/ibss.c
net/mac80211/ieee80211_i.h
net/mac80211/mesh.c
net/mac80211/tdls.c
net/mac80211/util.c

index 2001555..3b5874e 100644 (file)
@@ -188,7 +188,7 @@ ieee80211_ibss_build_presp(struct ieee80211_sub_if_data *sdata,
                 * keep them at 0
                 */
                pos = ieee80211_ie_build_ht_oper(pos, &sband->ht_cap,
-                                                chandef, 0);
+                                                chandef, 0, false);
 
                /* add VHT capability and information IEs */
                if (chandef->width != NL80211_CHAN_WIDTH_20 &&
index 68680ad..5c76ba7 100644 (file)
@@ -1962,7 +1962,7 @@ u8 *ieee80211_ie_build_ht_cap(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap,
                              u16 cap);
 u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap,
                               const struct cfg80211_chan_def *chandef,
-                              u16 prot_mode);
+                              u16 prot_mode, bool rifs_mode);
 u8 *ieee80211_ie_build_vht_cap(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap,
                               u32 cap);
 u8 *ieee80211_ie_build_vht_oper(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap,
index 626e8de..fa28500 100644 (file)
@@ -466,7 +466,8 @@ int mesh_add_ht_oper_ie(struct ieee80211_sub_if_data *sdata,
 
        pos = skb_put(skb, 2 + sizeof(struct ieee80211_ht_operation));
        ieee80211_ie_build_ht_oper(pos, ht_cap, &sdata->vif.bss_conf.chandef,
-                                  sdata->vif.bss_conf.ht_operation_mode);
+                                  sdata->vif.bss_conf.ht_operation_mode,
+                                  false);
 
        return 0;
 }
index ecc5e2a..c9eeb3f 100644 (file)
@@ -591,12 +591,19 @@ ieee80211_tdls_add_setup_cfm_ies(struct ieee80211_sub_if_data *sdata,
                offset = noffset;
        }
 
-       /* if HT support is only added in TDLS, we need an HT-operation IE */
+       /*
+        * if HT support is only added in TDLS, we need an HT-operation IE.
+        * add the IE as required by IEEE802.11-2012 9.23.3.2.
+        */
        if (!ap_sta->sta.ht_cap.ht_supported && sta->sta.ht_cap.ht_supported) {
+               u16 prot = IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED |
+                          IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT |
+                          IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT;
+
                pos = skb_put(skb, 2 + sizeof(struct ieee80211_ht_operation));
-               /* send an empty HT operation IE */
                ieee80211_ie_build_ht_oper(pos, &sta->sta.ht_cap,
-                                          &sdata->vif.bss_conf.chandef, 0);
+                                          &sdata->vif.bss_conf.chandef, prot,
+                                          true);
        }
 
        ieee80211_tdls_add_link_ie(sdata, skb, peer, initiator);
index d38daf0..8802aa4 100644 (file)
@@ -2292,7 +2292,7 @@ u8 *ieee80211_ie_build_vht_cap(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap,
 
 u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap,
                               const struct cfg80211_chan_def *chandef,
-                              u16 prot_mode)
+                              u16 prot_mode, bool rifs_mode)
 {
        struct ieee80211_ht_operation *ht_oper;
        /* Build HT Information */
@@ -2320,6 +2320,9 @@ u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap,
            chandef->width != NL80211_CHAN_WIDTH_20)
                ht_oper->ht_param |= IEEE80211_HT_PARAM_CHAN_WIDTH_ANY;
 
+       if (rifs_mode)
+               ht_oper->ht_param |= IEEE80211_HT_PARAM_RIFS_MODE;
+
        ht_oper->operation_mode = cpu_to_le16(prot_mode);
        ht_oper->stbc_param = 0x0000;