mac80211: rework encapsulation offload support
[openwrt/staging/wigyori.git] / package / kernel / mac80211 / patches / subsys / 310-mac80211-reduce-packet-loss-event-false-positives.patch
1 From: Felix Fietkau <nbd@nbd.name>
2 Date: Sat, 8 Aug 2020 19:20:02 +0200
3 Subject: [PATCH] mac80211: reduce packet loss event false positives
4
5 When running a large number of packets per second with a high data rate
6 and long A-MPDUs, the packet loss threshold can be reached very quickly
7 when the link conditions change. This frequently shows up as spurious
8 disconnects.
9 Mitigate false positives by using a similar logic for regular stations
10 as the one being used for TDLS, though with a more aggressive timeout.
11 Packet loss events are only reported if no ACK was received for a second.
12
13 Signed-off-by: Felix Fietkau <nbd@nbd.name>
14 ---
15
16 --- a/net/mac80211/sta_info.h
17 +++ b/net/mac80211/sta_info.h
18 @@ -522,7 +522,7 @@ struct ieee80211_sta_rx_stats {
19 * @status_stats.retry_failed: # of frames that failed after retry
20 * @status_stats.retry_count: # of retries attempted
21 * @status_stats.lost_packets: # of lost packets
22 - * @status_stats.last_tdls_pkt_time: timestamp of last TDLS packet
23 + * @status_stats.last_pkt_time: timestamp of last ACKed packet
24 * @status_stats.msdu_retries: # of MSDU retries
25 * @status_stats.msdu_failed: # of failed MSDUs
26 * @status_stats.last_ack: last ack timestamp (jiffies)
27 @@ -595,7 +595,7 @@ struct sta_info {
28 unsigned long filtered;
29 unsigned long retry_failed, retry_count;
30 unsigned int lost_packets;
31 - unsigned long last_tdls_pkt_time;
32 + unsigned long last_pkt_time;
33 u64 msdu_retries[IEEE80211_NUM_TIDS + 1];
34 u64 msdu_failed[IEEE80211_NUM_TIDS + 1];
35 unsigned long last_ack;
36 --- a/net/mac80211/status.c
37 +++ b/net/mac80211/status.c
38 @@ -749,12 +749,16 @@ static void ieee80211_report_used_skb(st
39 * - current throughput (higher value for higher tpt)?
40 */
41 #define STA_LOST_PKT_THRESHOLD 50
42 +#define STA_LOST_PKT_TIME HZ /* 1 sec since last ACK */
43 #define STA_LOST_TDLS_PKT_THRESHOLD 10
44 #define STA_LOST_TDLS_PKT_TIME (10*HZ) /* 10secs since last ACK */
45
46 static void ieee80211_lost_packet(struct sta_info *sta,
47 struct ieee80211_tx_info *info)
48 {
49 + unsigned long pkt_time = STA_LOST_PKT_TIME;
50 + unsigned int pkt_thr = STA_LOST_PKT_THRESHOLD;
51 +
52 /* If driver relies on its own algorithm for station kickout, skip
53 * mac80211 packet loss mechanism.
54 */
55 @@ -767,21 +771,20 @@ static void ieee80211_lost_packet(struct
56 return;
57
58 sta->status_stats.lost_packets++;
59 - if (!sta->sta.tdls &&
60 - sta->status_stats.lost_packets < STA_LOST_PKT_THRESHOLD)
61 - return;
62 + if (sta->sta.tdls) {
63 + pkt_time = STA_LOST_TDLS_PKT_TIME;
64 + pkt_thr = STA_LOST_PKT_THRESHOLD;
65 + }
66
67 /*
68 * If we're in TDLS mode, make sure that all STA_LOST_TDLS_PKT_THRESHOLD
69 * of the last packets were lost, and that no ACK was received in the
70 * last STA_LOST_TDLS_PKT_TIME ms, before triggering the CQM packet-loss
71 * mechanism.
72 + * For non-TDLS, use STA_LOST_PKT_THRESHOLD and STA_LOST_PKT_TIME
73 */
74 - if (sta->sta.tdls &&
75 - (sta->status_stats.lost_packets < STA_LOST_TDLS_PKT_THRESHOLD ||
76 - time_before(jiffies,
77 - sta->status_stats.last_tdls_pkt_time +
78 - STA_LOST_TDLS_PKT_TIME)))
79 + if (sta->status_stats.lost_packets < pkt_thr ||
80 + !time_after(jiffies, sta->status_stats.last_pkt_time + pkt_time))
81 return;
82
83 cfg80211_cqm_pktloss_notify(sta->sdata->dev, sta->sta.addr,
84 @@ -1034,9 +1037,7 @@ static void __ieee80211_tx_status(struct
85 sta->status_stats.lost_packets = 0;
86
87 /* Track when last TDLS packet was ACKed */
88 - if (test_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH))
89 - sta->status_stats.last_tdls_pkt_time =
90 - jiffies;
91 + sta->status_stats.last_pkt_time = jiffies;
92 } else if (noack_success) {
93 /* nothing to do here, do not account as lost */
94 } else {
95 @@ -1169,9 +1170,8 @@ void ieee80211_tx_status_ext(struct ieee
96 if (sta->status_stats.lost_packets)
97 sta->status_stats.lost_packets = 0;
98
99 - /* Track when last TDLS packet was ACKed */
100 - if (test_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH))
101 - sta->status_stats.last_tdls_pkt_time = jiffies;
102 + /* Track when last packet was ACKed */
103 + sta->status_stats.last_pkt_time = jiffies;
104 } else if (test_sta_flag(sta, WLAN_STA_PS_STA)) {
105 return;
106 } else if (noack_success) {
107 @@ -1260,8 +1260,7 @@ void ieee80211_tx_status_8023(struct iee
108 if (sta->status_stats.lost_packets)
109 sta->status_stats.lost_packets = 0;
110
111 - if (test_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH))
112 - sta->status_stats.last_tdls_pkt_time = jiffies;
113 + sta->status_stats.last_pkt_time = jiffies;
114 } else {
115 ieee80211_lost_packet(sta, info);
116 }