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
3 changed files with 93 additions and 77 deletions
|
@ -3306,82 +3306,14 @@ static const u64 care_about_ies =
|
||||||
(1ULL << WLAN_EID_HT_OPERATION) |
|
(1ULL << WLAN_EID_HT_OPERATION) |
|
||||||
(1ULL << WLAN_EID_EXT_CHANSWITCH_ANN);
|
(1ULL << WLAN_EID_EXT_CHANSWITCH_ANN);
|
||||||
|
|
||||||
static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
|
static void ieee80211_handle_beacon_sig(struct ieee80211_sub_if_data *sdata,
|
||||||
struct ieee80211_mgmt *mgmt, size_t len,
|
struct ieee80211_if_managed *ifmgd,
|
||||||
struct ieee80211_rx_status *rx_status)
|
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 */
|
/* Track average RSSI from the Beacon frames of the current AP */
|
||||||
|
|
||||||
if (ifmgd->flags & IEEE80211_STA_RESET_SIGNAL_AVE) {
|
if (ifmgd->flags & IEEE80211_STA_RESET_SIGNAL_AVE) {
|
||||||
ifmgd->flags &= ~IEEE80211_STA_RESET_SIGNAL_AVE;
|
ifmgd->flags &= ~IEEE80211_STA_RESET_SIGNAL_AVE;
|
||||||
ewma_beacon_signal_init(&ifmgd->ave_beacon_signal);
|
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);
|
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) {
|
if (ifmgd->flags & IEEE80211_STA_CONNECTION_POLL) {
|
||||||
mlme_dbg_ratelimited(sdata,
|
mlme_dbg_ratelimited(sdata,
|
||||||
|
|
|
@ -2804,7 +2804,8 @@ ieee80211_rx_h_mgmt_check(struct ieee80211_rx_data *rx)
|
||||||
!(rx->flags & IEEE80211_RX_BEACON_REPORTED)) {
|
!(rx->flags & IEEE80211_RX_BEACON_REPORTED)) {
|
||||||
int sig = 0;
|
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;
|
sig = status->signal;
|
||||||
|
|
||||||
cfg80211_report_obss_beacon(rx->local->hw.wiphy,
|
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.
|
* 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;
|
sig = status->signal;
|
||||||
|
|
||||||
if (cfg80211_rx_mgmt(&rx->sdata->wdev, status->freq, sig,
|
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;
|
bool signal_valid;
|
||||||
struct ieee80211_sub_if_data *scan_sdata;
|
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;
|
bss_meta.signal = rx_status->signal * 100;
|
||||||
else if (ieee80211_hw_check(&local->hw, SIGNAL_UNSPEC))
|
else if (ieee80211_hw_check(&local->hw, SIGNAL_UNSPEC))
|
||||||
bss_meta.signal = (rx_status->signal * 100) / local->hw.max_signal;
|
bss_meta.signal = (rx_status->signal * 100) / local->hw.max_signal;
|
||||||
|
|
Loading…
Add table
Reference in a new issue