@@ -808,6 +808,11 @@ enum mac80211_rate_control_flags {
*/
#define IEEE80211_STA_SIGNAL_AVE_MIN_COUNT 4
+/* Number of txrate count need to have been used in average station's
+ * txrate before checking against the threshold
+ */
+#define IEEE80211_STA_TXRATE_AVE_MIN_COUNT 4
+
/* there are 40 bytes if you don't need the rateset to be kept */
#define IEEE80211_TX_INFO_DRIVER_DATA_SIZE 40
@@ -3904,6 +3904,7 @@ static int ieee80211_set_sta_mon_txrate_config(struct wiphy *wiphy,
sta->txrate_low = low_txrate_thold;
sta->txrate_high = high_txrate_thold;
+ sta->last_txrate_event = 0;
unlock:
mutex_unlock(&sdata->local->sta_mtx);
@@ -419,6 +419,8 @@ struct ieee80211_sta_rx_stats {
*/
#define STA_SLOW_THRESHOLD 6000 /* 6 Mbps */
+DECLARE_EWMA(sta_txrate, 4, 4)
+
/**
* struct sta_info - STA information
*
@@ -501,6 +503,11 @@ struct ieee80211_sta_rx_stats {
* in 100Kbps
* @txrate_high: TXRATE upper threshold for a station to monitor, this will be
* in 100Kbps
+ * @count_sta_txrate: Number of transmitted data frames used in ave_sta_txrate
+ * @last_txrate_event: Last txrate event that triggered sta_mon event for a
+ * station
+ * @ave_sta_txrate: Average txrate to check against the txrate_low and
+ * txrate_high. Values expressed in 100kbps
*/
struct sta_info {
/* General information, mostly static */
@@ -611,6 +618,9 @@ struct sta_info {
u32 txrate_low;
u32 txrate_high;
+ unsigned int count_sta_txrate;
+ enum nl80211_sta_mon_txrate_threshold_event last_txrate_event;
+ struct ewma_sta_txrate ave_sta_txrate;
/* keep last! */
struct ieee80211_sta sta;
@@ -701,6 +701,40 @@ void ieee80211_tx_monitor(struct ieee80211_local *local, struct sk_buff *skb,
dev_kfree_skb(skb);
}
+static void ieee80211_sta_mon_txrate_thold_check(struct sta_info *sta)
+{
+ struct rate_info rinfo;
+ enum nl80211_sta_mon_txrate_threshold_event sta_txrate_event;
+ int txrate;
+
+ if (!sta->txrate_high)
+ return;
+
+ sta_set_rate_info_tx(sta, &sta->tx_stats.last_rate, &rinfo);
+ txrate = cfg80211_calculate_bitrate(&rinfo);
+ ewma_sta_txrate_add(&sta->ave_sta_txrate, txrate);
+ sta->count_sta_txrate++;
+
+ if (sta->count_sta_txrate < IEEE80211_STA_TXRATE_AVE_MIN_COUNT)
+ return;
+
+ txrate = ewma_sta_txrate_read(&sta->ave_sta_txrate);
+
+ if (txrate < sta->txrate_low)
+ sta_txrate_event = NL80211_STA_MON_TXRATE_THRESHOLD_EVENT_LOW;
+ else if (txrate > sta->txrate_high)
+ sta_txrate_event = NL80211_STA_MON_TXRATE_THRESHOLD_EVENT_HIGH;
+ else
+ sta_txrate_event = NL80211_STA_MON_TXRATE_THRESHOLD_IN_RANGE;
+
+ if (sta_txrate_event != sta->last_txrate_event) {
+ cfg80211_sta_mon_txrate_notify(sta->sdata->dev, sta->addr,
+ sta_txrate_event, txrate,
+ GFP_ATOMIC);
+ sta->last_txrate_event = sta_txrate_event;
+ }
+}
+
static void __ieee80211_tx_status(struct ieee80211_hw *hw,
struct ieee80211_tx_status *status)
{
@@ -750,9 +784,13 @@ static void __ieee80211_tx_status(struct ieee80211_hw *hw,
if (ieee80211_hw_check(&local->hw, HAS_RATE_CONTROL) &&
(ieee80211_is_data(hdr->frame_control)) &&
- (rates_idx != -1))
+ (rates_idx != -1)) {
sta->tx_stats.last_rate =
info->status.rates[rates_idx];
+ if (wiphy_ext_feature_isset(hw->wiphy,
+ NL80211_EXT_FEATURE_STA_MON_TXRATE_CONFIG))
+ ieee80211_sta_mon_txrate_thold_check(sta);
+ }
if ((info->flags & IEEE80211_TX_STAT_AMPDU_NO_BACK) &&
(ieee80211_is_data_qos(fc))) {
Trigger cfg80211_sta_mon_txrate_notify with the corresponding txrate event when the txrate for a station goes out of configured range. This event will be useful for the application like steering to take decision on any station depends on its current capability. Signed-off-by: Tamizh chelvam <tamizhr@codeaurora.org> --- include/net/mac80211.h | 5 +++++ net/mac80211/cfg.c | 1 + net/mac80211/sta_info.h | 10 ++++++++++ net/mac80211/status.c | 40 +++++++++++++++++++++++++++++++++++++++- 4 files changed, 55 insertions(+), 1 deletion(-)