|
|
@@ -0,0 +1,116 @@
|
|
|
+From: Felix Fietkau <[email protected]>
|
|
|
+Date: Sat, 8 Aug 2020 19:20:02 +0200
|
|
|
+Subject: [PATCH] mac80211: reduce packet loss event false positives
|
|
|
+
|
|
|
+When running a large number of packets per second with a high data rate
|
|
|
+and long A-MPDUs, the packet loss threshold can be reached very quickly
|
|
|
+when the link conditions change. This frequently shows up as spurious
|
|
|
+disconnects.
|
|
|
+Mitigate false positives by using a similar logic for regular stations
|
|
|
+as the one being used for TDLS, though with a more aggressive timeout.
|
|
|
+Packet loss events are only reported if no ACK was received for a second.
|
|
|
+
|
|
|
+Signed-off-by: Felix Fietkau <[email protected]>
|
|
|
+---
|
|
|
+
|
|
|
+--- a/net/mac80211/sta_info.h
|
|
|
++++ b/net/mac80211/sta_info.h
|
|
|
+@@ -522,7 +522,7 @@ struct ieee80211_sta_rx_stats {
|
|
|
+ * @status_stats.retry_failed: # of frames that failed after retry
|
|
|
+ * @status_stats.retry_count: # of retries attempted
|
|
|
+ * @status_stats.lost_packets: # of lost packets
|
|
|
+- * @status_stats.last_tdls_pkt_time: timestamp of last TDLS packet
|
|
|
++ * @status_stats.last_pkt_time: timestamp of last ACKed packet
|
|
|
+ * @status_stats.msdu_retries: # of MSDU retries
|
|
|
+ * @status_stats.msdu_failed: # of failed MSDUs
|
|
|
+ * @status_stats.last_ack: last ack timestamp (jiffies)
|
|
|
+@@ -595,7 +595,7 @@ struct sta_info {
|
|
|
+ unsigned long filtered;
|
|
|
+ unsigned long retry_failed, retry_count;
|
|
|
+ unsigned int lost_packets;
|
|
|
+- unsigned long last_tdls_pkt_time;
|
|
|
++ unsigned long last_pkt_time;
|
|
|
+ u64 msdu_retries[IEEE80211_NUM_TIDS + 1];
|
|
|
+ u64 msdu_failed[IEEE80211_NUM_TIDS + 1];
|
|
|
+ unsigned long last_ack;
|
|
|
+--- a/net/mac80211/status.c
|
|
|
++++ b/net/mac80211/status.c
|
|
|
+@@ -749,12 +749,16 @@ static void ieee80211_report_used_skb(st
|
|
|
+ * - current throughput (higher value for higher tpt)?
|
|
|
+ */
|
|
|
+ #define STA_LOST_PKT_THRESHOLD 50
|
|
|
++#define STA_LOST_PKT_TIME HZ /* 1 sec since last ACK */
|
|
|
+ #define STA_LOST_TDLS_PKT_THRESHOLD 10
|
|
|
+ #define STA_LOST_TDLS_PKT_TIME (10*HZ) /* 10secs since last ACK */
|
|
|
+
|
|
|
+ static void ieee80211_lost_packet(struct sta_info *sta,
|
|
|
+ struct ieee80211_tx_info *info)
|
|
|
+ {
|
|
|
++ unsigned long pkt_time = STA_LOST_PKT_TIME;
|
|
|
++ unsigned int pkt_thr = STA_LOST_PKT_THRESHOLD;
|
|
|
++
|
|
|
+ /* If driver relies on its own algorithm for station kickout, skip
|
|
|
+ * mac80211 packet loss mechanism.
|
|
|
+ */
|
|
|
+@@ -767,21 +771,20 @@ static void ieee80211_lost_packet(struct
|
|
|
+ return;
|
|
|
+
|
|
|
+ sta->status_stats.lost_packets++;
|
|
|
+- if (!sta->sta.tdls &&
|
|
|
+- sta->status_stats.lost_packets < STA_LOST_PKT_THRESHOLD)
|
|
|
+- return;
|
|
|
++ if (sta->sta.tdls) {
|
|
|
++ pkt_time = STA_LOST_TDLS_PKT_TIME;
|
|
|
++ pkt_thr = STA_LOST_PKT_THRESHOLD;
|
|
|
++ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ * If we're in TDLS mode, make sure that all STA_LOST_TDLS_PKT_THRESHOLD
|
|
|
+ * of the last packets were lost, and that no ACK was received in the
|
|
|
+ * last STA_LOST_TDLS_PKT_TIME ms, before triggering the CQM packet-loss
|
|
|
+ * mechanism.
|
|
|
++ * For non-TDLS, use STA_LOST_PKT_THRESHOLD and STA_LOST_PKT_TIME
|
|
|
+ */
|
|
|
+- if (sta->sta.tdls &&
|
|
|
+- (sta->status_stats.lost_packets < STA_LOST_TDLS_PKT_THRESHOLD ||
|
|
|
+- time_before(jiffies,
|
|
|
+- sta->status_stats.last_tdls_pkt_time +
|
|
|
+- STA_LOST_TDLS_PKT_TIME)))
|
|
|
++ if (sta->status_stats.lost_packets < pkt_thr ||
|
|
|
++ !time_after(jiffies, sta->status_stats.last_pkt_time + pkt_time))
|
|
|
+ return;
|
|
|
+
|
|
|
+ cfg80211_cqm_pktloss_notify(sta->sdata->dev, sta->sta.addr,
|
|
|
+@@ -1034,9 +1037,7 @@ static void __ieee80211_tx_status(struct
|
|
|
+ sta->status_stats.lost_packets = 0;
|
|
|
+
|
|
|
+ /* Track when last TDLS packet was ACKed */
|
|
|
+- if (test_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH))
|
|
|
+- sta->status_stats.last_tdls_pkt_time =
|
|
|
+- jiffies;
|
|
|
++ sta->status_stats.last_pkt_time = jiffies;
|
|
|
+ } else if (noack_success) {
|
|
|
+ /* nothing to do here, do not account as lost */
|
|
|
+ } else {
|
|
|
+@@ -1169,9 +1170,8 @@ void ieee80211_tx_status_ext(struct ieee
|
|
|
+ if (sta->status_stats.lost_packets)
|
|
|
+ sta->status_stats.lost_packets = 0;
|
|
|
+
|
|
|
+- /* Track when last TDLS packet was ACKed */
|
|
|
+- if (test_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH))
|
|
|
+- sta->status_stats.last_tdls_pkt_time = jiffies;
|
|
|
++ /* Track when last packet was ACKed */
|
|
|
++ sta->status_stats.last_pkt_time = jiffies;
|
|
|
+ } else if (test_sta_flag(sta, WLAN_STA_PS_STA)) {
|
|
|
+ return;
|
|
|
+ } else if (noack_success) {
|
|
|
+@@ -1260,8 +1260,7 @@ void ieee80211_tx_status_8023(struct iee
|
|
|
+ if (sta->status_stats.lost_packets)
|
|
|
+ sta->status_stats.lost_packets = 0;
|
|
|
+
|
|
|
+- if (test_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH))
|
|
|
+- sta->status_stats.last_tdls_pkt_time = jiffies;
|
|
|
++ sta->status_stats.last_pkt_time = jiffies;
|
|
|
+ } else {
|
|
|
+ ieee80211_lost_packet(sta, info);
|
|
|
+ }
|