From patchwork Wed Nov 1 15:29:25 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Larry Finger X-Patchwork-Id: 10036507 X-Patchwork-Delegate: kvalo@adurom.com Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 804E6603B5 for ; Wed, 1 Nov 2017 15:29:51 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 734C328628 for ; Wed, 1 Nov 2017 15:29:51 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 6816C2891D; Wed, 1 Nov 2017 15:29:51 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.6 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI, RCVD_IN_SORBS_SPAM, T_DKIM_INVALID, URIBL_BLACK autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 9F08F28628 for ; Wed, 1 Nov 2017 15:29:50 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754714AbdKAP3o (ORCPT ); Wed, 1 Nov 2017 11:29:44 -0400 Received: from mail-oi0-f68.google.com ([209.85.218.68]:49545 "EHLO mail-oi0-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754701AbdKAP3m (ORCPT ); Wed, 1 Nov 2017 11:29:42 -0400 Received: by mail-oi0-f68.google.com with SMTP id w197so5014464oif.6 for ; Wed, 01 Nov 2017 08:29:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references; bh=23udFca0cDo+37aMWvTy/Em2R7YorFW9sBngZvupK64=; b=OX/w0B4pqmnGiYZHALOrpnNV6w07EKlmMhymdFUH415vpMJOVxp2wAQ6Y8JpCtuhbV K59vyzzXQbyZ9UrnrtXEfE0vjZZm/4G1KyxVuCqm5cR/sz14NIrK4yy5+ImFsI/PYNGV YxSmN5jESGBY2xrzo0gmSB1aE/BvV1FIAOKKm+XcVH5tivnVDW+OFdJC8Hl7aFfTrTYp MFLL7OI93alerX21HasmwBfFEDMnZtiMN9nPtbO4cCUJY79jGJGj2ogn2fDXrWtb0PUa A5/LSu+tymhqh2fv/SGfMKVIvV4wyenwqrqkj0EFgl0Bz3G2M2OPeGxUU0uk3ASRNJ2k c32g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references; bh=23udFca0cDo+37aMWvTy/Em2R7YorFW9sBngZvupK64=; b=FcniUeXg3ZSa8zutTMr2Q1K5MzbjHKYKlx/7DhDRCHbDRJfPFXdqDslD5sv3AydrFx SGL71ps0zJDmkqJQQx++ieEly2WtQMri5azcSTYrhhdK2p8Y9tQ71tNLgvGcAWIkuZeM MNyhi6dbp0CQiX/5hy+nO+q4GgaDhcDp8dSR9qo84DlCnTlPyZPOPZlA8iQEZvukDn3F jVxNHb32hclfPPRXzlR7S89yhAsq6tJyK7QDlj2kHcFRVPjCqx780nKor6dvr5ZghDEC YqRqmPdTVvrNBlMIHm4IJcC0Wakn08so12WQQ21r5C+h2GRhmfiN05sfg4XxIZReNuIZ jkqg== X-Gm-Message-State: AMCzsaXZQqhnssxtfwYvcLWU3XoU/JxF+EehM7EsWjyoiVdU2eM+6sXC u9kxJY5Mj6W9lYzqLU7+Ha8= X-Google-Smtp-Source: ABhQp+RaZOtb+zC2U/71akHBE/uDigA9iOlVZb3hUvThFcWeZSmidKkXoQk9Ft4hxhYhBzdKPBbgWw== X-Received: by 10.202.93.213 with SMTP id r204mr112681oib.287.1509550181815; Wed, 01 Nov 2017 08:29:41 -0700 (PDT) Received: from Larrylap.localdomain (cpe-24-31-251-255.kc.res.rr.com. [24.31.251.255]) by smtp.gmail.com with ESMTPSA id v21sm338515ote.49.2017.11.01.08.29.40 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 01 Nov 2017 08:29:41 -0700 (PDT) From: Larry Finger To: kvalo@codeaurora.org Cc: linux-wireless@vger.kernel.org, Tsang-Shian Lin , Ping-Ke Shih , Larry Finger , Yan-Hsuan Chuang , Birming Chiu , Shaofu , Steven Ting Subject: [PATCH 10/11] rtlwifi: Add beacon check mechanism to check if AP settings changed. Date: Wed, 1 Nov 2017 10:29:25 -0500 Message-Id: <20171101152926.24971-11-Larry.Finger@lwfinger.net> X-Mailer: git-send-email 2.14.3 In-Reply-To: <20171101152926.24971-1-Larry.Finger@lwfinger.net> References: <20171101152926.24971-1-Larry.Finger@lwfinger.net> Sender: linux-wireless-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Tsang-Shian Lin AP WiFi settings are changed(channel, bandwidth), but deauth may not received by STA. For these cases, we need to detect and handle beacon changes. Signed-off-by: Tsang-Shian Lin Signed-off-by: Ping-Ke Shih Signed-off-by: Larry Finger Cc: Yan-Hsuan Chuang Cc: Birming Chiu Cc: Shaofu Cc: Steven Ting --- drivers/net/wireless/realtek/rtlwifi/base.c | 179 ++++++++++++++++++++++++++++ drivers/net/wireless/realtek/rtlwifi/base.h | 3 +- drivers/net/wireless/realtek/rtlwifi/core.c | 48 ++++++++ drivers/net/wireless/realtek/rtlwifi/pci.c | 2 + drivers/net/wireless/realtek/rtlwifi/wifi.h | 13 ++ 5 files changed, 244 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/realtek/rtlwifi/base.c b/drivers/net/wireless/realtek/rtlwifi/base.c index 7e3107f9e37f..35eeb602325d 100644 --- a/drivers/net/wireless/realtek/rtlwifi/base.c +++ b/drivers/net/wireless/realtek/rtlwifi/base.c @@ -2362,6 +2362,185 @@ struct sk_buff *rtl_make_del_ba(struct ieee80211_hw *hw, return skb; } +bool rtl_check_beacon_key(struct ieee80211_hw *hw, void *data, unsigned int len) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_phy *rtlphy = &rtlpriv->phy; + struct ieee80211_hdr *hdr = data; + struct ieee80211_ht_cap *ht_cap_ie; + struct ieee80211_ht_operation *ht_oper_ie = NULL; + struct rtl_beacon_keys bcn_key = {0}; + struct rtl_beacon_keys *cur_bcn_key; + u8 *ht_cap; + u8 ht_cap_len; + u8 *ht_oper; + u8 ht_oper_len; + u8 *ds_param; + u8 ds_param_len; + + if (mac->opmode != NL80211_IFTYPE_STATION) + return false; + + /* check if this really is a beacon*/ + if (!ieee80211_is_beacon(hdr->frame_control)) + return false; + + /* min. beacon length + FCS_LEN */ + if (len <= 40 + FCS_LEN) + return false; + + cur_bcn_key = &mac->cur_beacon_keys; + + if (rtlpriv->mac80211.link_state == MAC80211_NOLINK) { + if (cur_bcn_key->valid) { + cur_bcn_key->valid = false; + RT_TRACE(rtlpriv, COMP_BEACON, DBG_LOUD, + "Reset cur_beacon_keys.valid to false!\n"); + } + return false; + } + + /* and only beacons from the associated BSSID, please */ + if (!ether_addr_equal(hdr->addr3, rtlpriv->mac80211.bssid)) + return false; + + /***** Parsing DS Param IE ******/ + ds_param = rtl_find_ie(data, len - FCS_LEN, WLAN_EID_DS_PARAMS); + + if (ds_param && !(ds_param[1] < sizeof(*ds_param))) + ds_param_len = ds_param[1]; + else + ds_param = NULL; + + /***** Parsing HT Cap. IE ******/ + ht_cap = rtl_find_ie(data, len - FCS_LEN, WLAN_EID_HT_CAPABILITY); + + if (ht_cap && !(ht_cap[1] < sizeof(*ht_cap))) { + ht_cap_len = ht_cap[1]; + ht_cap_ie = (struct ieee80211_ht_cap *)&ht_cap[2]; + } else { + ht_cap = NULL; + ht_cap_ie = NULL; + } + + /***** Parsing HT Info. IE ******/ + ht_oper = rtl_find_ie(data, len - FCS_LEN, WLAN_EID_HT_OPERATION); + + if (ht_oper && !(ht_oper[1] < sizeof(*ht_oper))) { + ht_oper_len = ht_oper[1]; + ht_oper_ie = (struct ieee80211_ht_operation *)&ht_oper[2]; + } else { + ht_oper = NULL; + } + + /* update bcn_key */ + memset(&bcn_key, 0, sizeof(bcn_key)); + + if (ds_param) + bcn_key.bcn_channel = ds_param[2]; + else if (ht_oper && ht_oper_ie) + bcn_key.bcn_channel = ht_oper_ie->primary_chan; + + if (ht_cap_ie) + bcn_key.ht_cap_info = ht_cap_ie->cap_info; + + if (ht_oper && ht_oper_ie) + bcn_key.ht_info_infos_0_sco = ht_oper_ie->ht_param & 0x03; + + bcn_key.valid = true; + + /* update cur_beacon_keys or compare beacon key */ + if (rtlpriv->mac80211.link_state != MAC80211_LINKED && + rtlpriv->mac80211.link_state != MAC80211_LINKED_SCANNING) + return true; + + if (!cur_bcn_key->valid) { + /* update cur_beacon_keys */ + memset(cur_bcn_key, 0, sizeof(bcn_key)); + memcpy(cur_bcn_key, &bcn_key, sizeof(bcn_key)); + cur_bcn_key->valid = true; + + RT_TRACE(rtlpriv, COMP_BEACON, DBG_LOUD, + "Beacon key update!ch=%d, ht_cap_info=0x%x, sco=0x%x\n", + cur_bcn_key->bcn_channel, + cur_bcn_key->ht_cap_info, + cur_bcn_key->ht_info_infos_0_sco); + + return true; + } + + /* compare beacon key */ + if (!memcmp(cur_bcn_key, &bcn_key, sizeof(bcn_key))) { + /* same beacon key */ + mac->new_beacon_cnt = 0; + goto chk_exit; + } + + if (cur_bcn_key->bcn_channel == bcn_key.bcn_channel && + cur_bcn_key->ht_cap_info == bcn_key.ht_cap_info) { + /* Beacon HT info IE, secondary channel offset check */ + /* 40M -> 20M */ + if (cur_bcn_key->ht_info_infos_0_sco > + bcn_key.ht_info_infos_0_sco) { + /* Not a new beacon */ + RT_TRACE(rtlpriv, COMP_BEACON, DBG_DMESG, + "Beacon BW change! sco:0x%x -> 0x%x\n", + cur_bcn_key->ht_info_infos_0_sco, + bcn_key.ht_info_infos_0_sco); + + cur_bcn_key->ht_info_infos_0_sco = + bcn_key.ht_info_infos_0_sco; + } else { + /* 20M -> 40M */ + if (rtlphy->max_ht_chan_bw >= HT_CHANNEL_WIDTH_20_40) { + /* Not a new beacon */ + RT_TRACE(rtlpriv, COMP_BEACON, DBG_DMESG, + "Beacon BW change! sco:0x%x -> 0x%x\n", + cur_bcn_key->ht_info_infos_0_sco, + bcn_key.ht_info_infos_0_sco); + + cur_bcn_key->ht_info_infos_0_sco = + bcn_key.ht_info_infos_0_sco; + } else { + mac->new_beacon_cnt++; + } + } + } else { + mac->new_beacon_cnt++; + } + + if (mac->new_beacon_cnt == 1) { + RT_TRACE(rtlpriv, COMP_BEACON, DBG_DMESG, + "Get new beacon.\n"); + RT_TRACE(rtlpriv, COMP_BEACON, DBG_DMESG, + "Cur : ch=%d, ht_cap=0x%x, sco=0x%x\n", + cur_bcn_key->bcn_channel, + cur_bcn_key->ht_cap_info, + cur_bcn_key->ht_info_infos_0_sco); + RT_TRACE(rtlpriv, COMP_BEACON, DBG_DMESG, + "New RX : ch=%d, ht_cap=0x%x, sco=0x%x\n", + bcn_key.bcn_channel, + bcn_key.ht_cap_info, + bcn_key.ht_info_infos_0_sco); + + } else if (mac->new_beacon_cnt > 1) { + RT_TRACE(rtlpriv, COMP_BEACON, DBG_DMESG, + "new beacon cnt: %d\n", + mac->new_beacon_cnt); + } + + if (mac->new_beacon_cnt > 3) { + ieee80211_connection_loss(rtlpriv->mac80211.vif); + RT_TRACE(rtlpriv, COMP_BEACON, DBG_DMESG, + "new beacon cnt >3, disconnect !\n"); + } + +chk_exit: + + return true; +} +EXPORT_SYMBOL_GPL(rtl_check_beacon_key); /********************************************************* * * IOT functions diff --git a/drivers/net/wireless/realtek/rtlwifi/base.h b/drivers/net/wireless/realtek/rtlwifi/base.h index 26735319b38f..3ad8e8107209 100644 --- a/drivers/net/wireless/realtek/rtlwifi/base.h +++ b/drivers/net/wireless/realtek/rtlwifi/base.h @@ -176,5 +176,6 @@ u8 rtl_tid_to_ac(u8 tid); void rtl_easy_concurrent_retrytimer_callback(struct timer_list *t); extern struct rtl_global_var rtl_global_var; void rtl_phy_scan_operation_backup(struct ieee80211_hw *hw, u8 operation); - +bool rtl_check_beacon_key(struct ieee80211_hw *hw, void *data, + unsigned int len); #endif diff --git a/drivers/net/wireless/realtek/rtlwifi/core.c b/drivers/net/wireless/realtek/rtlwifi/core.c index 1147327e6f52..db0cc2cb4b0a 100644 --- a/drivers/net/wireless/realtek/rtlwifi/core.c +++ b/drivers/net/wireless/realtek/rtlwifi/core.c @@ -911,6 +911,7 @@ static int rtl_op_sta_add(struct ieee80211_hw *hw, struct ieee80211_sta *sta) { struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); struct rtl_sta_info *sta_entry; @@ -943,6 +944,16 @@ static int rtl_op_sta_add(struct ieee80211_hw *hw, if (mac->p2p) sta->supp_rates[0] &= 0xfffffff0; + if (sta->ht_cap.ht_supported) { + if (sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) + rtlphy->max_ht_chan_bw = HT_CHANNEL_WIDTH_20_40; + else + rtlphy->max_ht_chan_bw = HT_CHANNEL_WIDTH_20; + } + + if (sta->vht_cap.vht_supported) + rtlphy->max_vht_chan_bw = HT_CHANNEL_WIDTH_80; + memcpy(sta_entry->mac_addr, sta->addr, ETH_ALEN); RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, "Add sta addr is %pM\n", sta->addr); @@ -1041,6 +1052,7 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw, u32 changed) { struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; struct rtl_hal *rtlhal = rtl_hal(rtlpriv); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); @@ -1243,6 +1255,16 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw, mac->current_ampdu_factor) mac->current_ampdu_factor = sta->ht_cap.ampdu_factor; + + if (sta->ht_cap.ht_supported) { + if (sta->ht_cap.cap & + IEEE80211_HT_CAP_SUP_WIDTH_20_40) + rtlphy->max_ht_chan_bw = + HT_CHANNEL_WIDTH_20_40; + else + rtlphy->max_ht_chan_bw = + HT_CHANNEL_WIDTH_20; + } } rcu_read_unlock(); @@ -1254,6 +1276,32 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw, &mac->current_ampdu_density); } + if (changed & BSS_CHANGED_BANDWIDTH) { + struct ieee80211_sta *sta = NULL; + + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, + "BSS_CHANGED_BANDWIDTH\n"); + + rcu_read_lock(); + sta = ieee80211_find_sta(vif, (u8 *)bss_conf->bssid); + + if (sta) { + if (sta->ht_cap.ht_supported) { + if (sta->ht_cap.cap & + IEEE80211_HT_CAP_SUP_WIDTH_20_40) + rtlphy->max_ht_chan_bw = + HT_CHANNEL_WIDTH_20_40; + else + rtlphy->max_ht_chan_bw = + HT_CHANNEL_WIDTH_20; + } + + if (sta->vht_cap.vht_supported) + rtlphy->max_vht_chan_bw = HT_CHANNEL_WIDTH_80; + } + rcu_read_unlock(); + } + if (changed & BSS_CHANGED_BSSID) { u32 basic_rates; struct ieee80211_sta *sta = NULL; diff --git a/drivers/net/wireless/realtek/rtlwifi/pci.c b/drivers/net/wireless/realtek/rtlwifi/pci.c index 0a2766385ca2..01c93721eca9 100644 --- a/drivers/net/wireless/realtek/rtlwifi/pci.c +++ b/drivers/net/wireless/realtek/rtlwifi/pci.c @@ -877,6 +877,8 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw) ieee80211_is_probe_resp(fc))) { dev_kfree_skb_any(skb); } else { + rtl_check_beacon_key(hw, (void *)skb->data, + skb->len); _rtl_pci_rx_to_mac80211(hw, skb, rx_status); } } else { diff --git a/drivers/net/wireless/realtek/rtlwifi/wifi.h b/drivers/net/wireless/realtek/rtlwifi/wifi.h index 49f6918ae18b..babf586fa21c 100644 --- a/drivers/net/wireless/realtek/rtlwifi/wifi.h +++ b/drivers/net/wireless/realtek/rtlwifi/wifi.h @@ -962,6 +962,15 @@ struct rtl_probe_rsp { struct rtl_info_element info_element[0]; } __packed; +struct rtl_beacon_keys { + /*u8 ssid[32];*/ + /*u32 ssid_len;*/ + u8 bcn_channel; + __le16 ht_cap_info; + u8 ht_info_infos_0_sco; /* bit0 & bit1 in infos[0] is 2nd ch offset */ + bool valid; +}; + /*LED related.*/ /*ledpin Identify how to implement this SW led.*/ struct rtl_led { @@ -1209,6 +1218,8 @@ struct rtl_phy { u8 rf_mode; u8 rf_type; u8 current_chan_bw; + u8 max_ht_chan_bw; + u8 max_vht_chan_bw; u8 set_bwmode_inprogress; u8 sw_chnl_inprogress; u8 sw_chnl_stage; @@ -1380,6 +1391,8 @@ struct rtl_mac { /*Probe Beacon management */ struct rtl_tid_data tids[MAX_TID_COUNT]; enum rtl_link_state link_state; + struct rtl_beacon_keys cur_beacon_keys; + u8 new_beacon_cnt; int n_channels; int n_bitrates;