mac80211: implement packet loss notification
authorJohannes Berg <johannes.berg@intel.com>
Wed, 24 Nov 2010 07:10:06 +0000 (08:10 +0100)
committerJohn W. Linville <linville@tuxdriver.com>
Wed, 24 Nov 2010 21:19:36 +0000 (16:19 -0500)
For drivers that have accurate TX status reporting
we can report the number of consecutive lost packets
to userspace using the new cfg80211 CQM event. The
threshold is fixed right now, this may need to be
improved in the future.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
net/mac80211/sta_info.h
net/mac80211/status.c

index 9265acadef32d862c11889c2d96575147fcec972..b562d9b6a7023f84ce3659645ee4663b5aa04605 100644 (file)
@@ -248,6 +248,7 @@ enum plink_state {
  * @sta: station information we share with the driver
  * @dead: set to true when sta is unlinked
  * @uploaded: set to true when sta is uploaded to the driver
+ * @lost_packets: number of consecutive lost packets
  */
 struct sta_info {
        /* General information, mostly static */
@@ -335,6 +336,8 @@ struct sta_info {
        } debugfs;
 #endif
 
+       unsigned int lost_packets;
+
        /* keep last! */
        struct ieee80211_sta sta;
 };
index 8695cd11dfd95b8b5df5692ea1a5d6c1a11d5415..bed7e32ed9085fd1c5a605618c6168910fa1cc25 100644 (file)
@@ -161,6 +161,15 @@ static void ieee80211_frame_acked(struct sta_info *sta, struct sk_buff *skb)
                ieee80211_sta_tx_notify(sdata, (void *) skb->data);
 }
 
+/*
+ * Use a static threshold for now, best value to be determined
+ * by testing ...
+ * Should it depend on:
+ *  - on # of retransmissions
+ *  - current throughput (higher value for higher tpt)?
+ */
+#define STA_LOST_PKT_THRESHOLD 50
+
 void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
 {
        struct sk_buff *skb2;
@@ -247,6 +256,19 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
                if (!(info->flags & IEEE80211_TX_CTL_INJECTED) &&
                    (info->flags & IEEE80211_TX_STAT_ACK))
                        ieee80211_frame_acked(sta, skb);
+
+               if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) {
+                       if (info->flags & IEEE80211_TX_STAT_ACK) {
+                               if (sta->lost_packets)
+                                       sta->lost_packets = 0;
+                       } else if (++sta->lost_packets >= STA_LOST_PKT_THRESHOLD) {
+                               cfg80211_cqm_pktloss_notify(sta->sdata->dev,
+                                                           sta->sta.addr,
+                                                           sta->lost_packets,
+                                                           GFP_ATOMIC);
+                               sta->lost_packets = 0;
+                       }
+               }
        }
 
        rcu_read_unlock();