OSDN Git Service

mac80211: inform wireless layer when frame RSSI is invalid
authorTosoni <jp.tosoni@acksys.fr>
Wed, 14 Mar 2018 16:58:34 +0000 (16:58 +0000)
committerJohannes Berg <johannes.berg@intel.com>
Wed, 21 Mar 2018 10:27:11 +0000 (11:27 +0100)
When the low-level driver returns an invalid RSSI indication,
set the signal value to 0 as an indication to the upper layer.

Also, skip average level computation if signal is invalid.

Signed-off-by: Jean Pierre TOSONI <jp.tosoni@acksys.fr>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
net/mac80211/mlme.c
net/mac80211/rx.c
net/mac80211/scan.c

index 0024eff..ea3ba03 100644 (file)
@@ -3306,82 +3306,14 @@ static const u64 care_about_ies =
        (1ULL << WLAN_EID_HT_OPERATION) |
        (1ULL << WLAN_EID_EXT_CHANSWITCH_ANN);
 
-static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
-                                    struct ieee80211_mgmt *mgmt, size_t len,
-                                    struct ieee80211_rx_status *rx_status)
+static void ieee80211_handle_beacon_sig(struct ieee80211_sub_if_data *sdata,
+                                       struct ieee80211_if_managed *ifmgd,
+                                       struct ieee80211_bss_conf *bss_conf,
+                                       struct ieee80211_local *local,
+                                       struct ieee80211_rx_status *rx_status)
 {
-       struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
-       struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf;
-       size_t baselen;
-       struct ieee802_11_elems elems;
-       struct ieee80211_local *local = sdata->local;
-       struct ieee80211_chanctx_conf *chanctx_conf;
-       struct ieee80211_channel *chan;
-       struct sta_info *sta;
-       u32 changed = 0;
-       bool erp_valid;
-       u8 erp_value = 0;
-       u32 ncrc;
-       u8 *bssid;
-       u8 deauth_buf[IEEE80211_DEAUTH_FRAME_LEN];
-
-       sdata_assert_lock(sdata);
-
-       /* Process beacon from the current BSS */
-       baselen = (u8 *) mgmt->u.beacon.variable - (u8 *) mgmt;
-       if (baselen > len)
-               return;
-
-       rcu_read_lock();
-       chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
-       if (!chanctx_conf) {
-               rcu_read_unlock();
-               return;
-       }
-
-       if (rx_status->freq != chanctx_conf->def.chan->center_freq) {
-               rcu_read_unlock();
-               return;
-       }
-       chan = chanctx_conf->def.chan;
-       rcu_read_unlock();
-
-       if (ifmgd->assoc_data && ifmgd->assoc_data->need_beacon &&
-           ether_addr_equal(mgmt->bssid, ifmgd->assoc_data->bss->bssid)) {
-               ieee802_11_parse_elems(mgmt->u.beacon.variable,
-                                      len - baselen, false, &elems);
-
-               ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems);
-               if (elems.tim && !elems.parse_error) {
-                       const struct ieee80211_tim_ie *tim_ie = elems.tim;
-                       ifmgd->dtim_period = tim_ie->dtim_period;
-               }
-               ifmgd->have_beacon = true;
-               ifmgd->assoc_data->need_beacon = false;
-               if (ieee80211_hw_check(&local->hw, TIMING_BEACON_ONLY)) {
-                       sdata->vif.bss_conf.sync_tsf =
-                               le64_to_cpu(mgmt->u.beacon.timestamp);
-                       sdata->vif.bss_conf.sync_device_ts =
-                               rx_status->device_timestamp;
-                       if (elems.tim)
-                               sdata->vif.bss_conf.sync_dtim_count =
-                                       elems.tim->dtim_count;
-                       else
-                               sdata->vif.bss_conf.sync_dtim_count = 0;
-               }
-               /* continue assoc process */
-               ifmgd->assoc_data->timeout = jiffies;
-               ifmgd->assoc_data->timeout_started = true;
-               run_again(sdata, ifmgd->assoc_data->timeout);
-               return;
-       }
-
-       if (!ifmgd->associated ||
-           !ether_addr_equal(mgmt->bssid, ifmgd->associated->bssid))
-               return;
-       bssid = ifmgd->associated->bssid;
-
        /* Track average RSSI from the Beacon frames of the current AP */
+
        if (ifmgd->flags & IEEE80211_STA_RESET_SIGNAL_AVE) {
                ifmgd->flags &= ~IEEE80211_STA_RESET_SIGNAL_AVE;
                ewma_beacon_signal_init(&ifmgd->ave_beacon_signal);
@@ -3468,6 +3400,86 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
                                sig, GFP_KERNEL);
                }
        }
+}
+
+static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
+                                    struct ieee80211_mgmt *mgmt, size_t len,
+                                    struct ieee80211_rx_status *rx_status)
+{
+       struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
+       struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf;
+       size_t baselen;
+       struct ieee802_11_elems elems;
+       struct ieee80211_local *local = sdata->local;
+       struct ieee80211_chanctx_conf *chanctx_conf;
+       struct ieee80211_channel *chan;
+       struct sta_info *sta;
+       u32 changed = 0;
+       bool erp_valid;
+       u8 erp_value = 0;
+       u32 ncrc;
+       u8 *bssid;
+       u8 deauth_buf[IEEE80211_DEAUTH_FRAME_LEN];
+
+       sdata_assert_lock(sdata);
+
+       /* Process beacon from the current BSS */
+       baselen = (u8 *) mgmt->u.beacon.variable - (u8 *) mgmt;
+       if (baselen > len)
+               return;
+
+       rcu_read_lock();
+       chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
+       if (!chanctx_conf) {
+               rcu_read_unlock();
+               return;
+       }
+
+       if (rx_status->freq != chanctx_conf->def.chan->center_freq) {
+               rcu_read_unlock();
+               return;
+       }
+       chan = chanctx_conf->def.chan;
+       rcu_read_unlock();
+
+       if (ifmgd->assoc_data && ifmgd->assoc_data->need_beacon &&
+           ether_addr_equal(mgmt->bssid, ifmgd->assoc_data->bss->bssid)) {
+               ieee802_11_parse_elems(mgmt->u.beacon.variable,
+                                      len - baselen, false, &elems);
+
+               ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems);
+               if (elems.tim && !elems.parse_error) {
+                       const struct ieee80211_tim_ie *tim_ie = elems.tim;
+                       ifmgd->dtim_period = tim_ie->dtim_period;
+               }
+               ifmgd->have_beacon = true;
+               ifmgd->assoc_data->need_beacon = false;
+               if (ieee80211_hw_check(&local->hw, TIMING_BEACON_ONLY)) {
+                       sdata->vif.bss_conf.sync_tsf =
+                               le64_to_cpu(mgmt->u.beacon.timestamp);
+                       sdata->vif.bss_conf.sync_device_ts =
+                               rx_status->device_timestamp;
+                       if (elems.tim)
+                               sdata->vif.bss_conf.sync_dtim_count =
+                                       elems.tim->dtim_count;
+                       else
+                               sdata->vif.bss_conf.sync_dtim_count = 0;
+               }
+               /* continue assoc process */
+               ifmgd->assoc_data->timeout = jiffies;
+               ifmgd->assoc_data->timeout_started = true;
+               run_again(sdata, ifmgd->assoc_data->timeout);
+               return;
+       }
+
+       if (!ifmgd->associated ||
+           !ether_addr_equal(mgmt->bssid, ifmgd->associated->bssid))
+               return;
+       bssid = ifmgd->associated->bssid;
+
+       if (!(rx_status->flag & RX_FLAG_NO_SIGNAL_VAL))
+               ieee80211_handle_beacon_sig(sdata, ifmgd, bss_conf,
+                                           local, rx_status);
 
        if (ifmgd->flags & IEEE80211_STA_CONNECTION_POLL) {
                mlme_dbg_ratelimited(sdata,
index 9c898a3..27bb1f0 100644 (file)
@@ -2804,7 +2804,8 @@ ieee80211_rx_h_mgmt_check(struct ieee80211_rx_data *rx)
            !(rx->flags & IEEE80211_RX_BEACON_REPORTED)) {
                int sig = 0;
 
-               if (ieee80211_hw_check(&rx->local->hw, SIGNAL_DBM))
+               if (ieee80211_hw_check(&rx->local->hw, SIGNAL_DBM) &&
+                   !(status->flag & RX_FLAG_NO_SIGNAL_VAL))
                        sig = status->signal;
 
                cfg80211_report_obss_beacon(rx->local->hw.wiphy,
@@ -3145,7 +3146,8 @@ ieee80211_rx_h_userspace_mgmt(struct ieee80211_rx_data *rx)
         * it transmitted were processed or returned.
         */
 
-       if (ieee80211_hw_check(&rx->local->hw, SIGNAL_DBM))
+       if (ieee80211_hw_check(&rx->local->hw, SIGNAL_DBM) &&
+           !(status->flag & RX_FLAG_NO_SIGNAL_VAL))
                sig = status->signal;
 
        if (cfg80211_rx_mgmt(&rx->sdata->wdev, status->freq, sig,
index ef2beca..a3b1bcc 100644 (file)
@@ -73,7 +73,9 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
        bool signal_valid;
        struct ieee80211_sub_if_data *scan_sdata;
 
-       if (ieee80211_hw_check(&local->hw, SIGNAL_DBM))
+       if (rx_status->flag & RX_FLAG_NO_SIGNAL_VAL)
+               bss_meta.signal = 0; /* invalid signal indication */
+       else if (ieee80211_hw_check(&local->hw, SIGNAL_DBM))
                bss_meta.signal = rx_status->signal * 100;
        else if (ieee80211_hw_check(&local->hw, SIGNAL_UNSPEC))
                bss_meta.signal = (rx_status->signal * 100) / local->hw.max_signal;