forked from Minki/linux
mac80211: inform wireless layer when frame RSSI is invalid
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>
This commit is contained in:
parent
8cfd36a0b5
commit
1ad22fb5bb
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user