mac80211: optimize station connection monitor

Calling mod_timer for every rx/tx packet can be quite expensive.
Instead of constantly updating the timer, we can simply let it run out
and check the timestamp of the last ACK or rx packet to re-arm it.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
Link: https://lore.kernel.org/r/20200908123702.88454-9-nbd@nbd.name
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
Felix Fietkau
2020-09-08 14:36:56 +02:00
committed by Johannes Berg
parent 1ff4e8f2de
commit 9abf4e4983
5 changed files with 22 additions and 47 deletions

View File

@@ -2432,23 +2432,6 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM;
}
void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata,
struct ieee80211_hdr *hdr)
{
/*
* We can postpone the mgd.timer whenever receiving unicast frames
* from AP because we know that the connection is working both ways
* at that time. But multicast frames (and hence also beacons) must
* be ignored here, because we need to trigger the timer during
* data idle periods for sending the periodic probe request to the
* AP we're connected to.
*/
if (is_multicast_ether_addr(hdr->addr1))
return;
ieee80211_sta_reset_conn_monitor(sdata);
}
static void ieee80211_reset_ap_probe(struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
@@ -2521,21 +2504,13 @@ void ieee80211_sta_tx_notify(struct ieee80211_sub_if_data *sdata,
{
ieee80211_sta_tx_wmm_ac_notify(sdata, hdr, tx_time);
if (!ieee80211_is_data(hdr->frame_control))
return;
if (ieee80211_is_any_nullfunc(hdr->frame_control) &&
sdata->u.mgd.probe_send_count > 0) {
if (ack)
ieee80211_sta_reset_conn_monitor(sdata);
else
sdata->u.mgd.nullfunc_failed = true;
ieee80211_queue_work(&sdata->local->hw, &sdata->work);
if (!ieee80211_is_any_nullfunc(hdr->frame_control) ||
!sdata->u.mgd.probe_send_count)
return;
}
if (ack)
ieee80211_sta_reset_conn_monitor(sdata);
if (!ack)
sdata->u.mgd.nullfunc_failed = true;
ieee80211_queue_work(&sdata->local->hw, &sdata->work);
}
static void ieee80211_mlme_send_probe_req(struct ieee80211_sub_if_data *sdata,
@@ -3608,8 +3583,8 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
* Start timer to probe the connection to the AP now.
* Also start the timer that will detect beacon loss.
*/
ieee80211_sta_rx_notify(sdata, (struct ieee80211_hdr *)mgmt);
ieee80211_sta_reset_beacon_monitor(sdata);
ieee80211_sta_reset_conn_monitor(sdata);
ret = true;
out:
@@ -4580,10 +4555,26 @@ static void ieee80211_sta_conn_mon_timer(struct timer_list *t)
from_timer(sdata, t, u.mgd.conn_mon_timer);
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
struct ieee80211_local *local = sdata->local;
struct sta_info *sta;
unsigned long timeout;
if (sdata->vif.csa_active && !ifmgd->csa_waiting_bcn)
return;
sta = sta_info_get(sdata, ifmgd->bssid);
if (!sta)
return;
timeout = sta->status_stats.last_ack;
if (time_before(sta->status_stats.last_ack, sta->rx_stats.last_rx))
timeout = sta->rx_stats.last_rx;
timeout += IEEE80211_CONNECTION_IDLE_TIME;
if (time_is_before_jiffies(timeout)) {
mod_timer(&ifmgd->conn_mon_timer, round_jiffies_up(timeout));
return;
}
ieee80211_queue_work(&local->hw, &ifmgd->monitor_work);
}