mac80211: Decouple fail_avg stats used by mesh from rate control algorithm.
authorJavier Cardona <javier@cozybit.com>
Tue, 18 Aug 2009 00:15:55 +0000 (17:15 -0700)
committerJohn W. Linville <linville@tuxdriver.com>
Thu, 20 Aug 2009 15:36:02 +0000 (11:36 -0400)
Mesh uses the tx failure average to compute the (m)path metric.  This used to
be done inside the rate control module.  This patch breaks the dependency
between the mesh stack and the rate control algorithm.  Mesh will now work
independently of the chosen rate control algorithm.

The mesh stack keeps a moving average of the average transmission losses for
each mesh peer station.  If the fail average exceeds a certain threshold, the
peer link is marked as broken.

Signed-off-by: Javier Cardona <javier@cozybit.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
net/mac80211/main.c
net/mac80211/mesh.h
net/mac80211/mesh_hwmp.c
net/mac80211/rc80211_minstrel.c
net/mac80211/rc80211_pid_algo.c

index 3302df96f8d4d9932fa9fecfb9f6deadf1ead7da..f80efd7ff5eca20cc1550b4e3b31e8e05e03f3fb 100644 (file)
@@ -482,6 +482,8 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
                }
 
                rate_control_tx_status(local, sband, sta, skb);
+               if (ieee80211_vif_is_mesh(&sta->sdata->vif))
+                       ieee80211s_update_metric(local, sta, skb);
        }
 
        rcu_read_unlock();
index eb23fc639b2bba6ab5c37117ac4da3671f350999..dd1c19319f0a8c3073e4e01f147e58620e8b3c8c 100644 (file)
@@ -226,6 +226,8 @@ void mesh_mgmt_ies_add(struct sk_buff *skb,
 void mesh_rmc_free(struct ieee80211_sub_if_data *sdata);
 int mesh_rmc_init(struct ieee80211_sub_if_data *sdata);
 void ieee80211s_init(void);
+void ieee80211s_update_metric(struct ieee80211_local *local,
+               struct sta_info *stainfo, struct sk_buff *skb);
 void ieee80211s_stop(void);
 void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata);
 ieee80211_rx_result
index ef1efd362691ce29cb93f18e94400eb6a4389e3f..7aeba00ac502d0ca1b21993f4874ffd8f3c07f9a 100644 (file)
@@ -201,6 +201,24 @@ int mesh_path_error_tx(u8 *dst, __le32 dst_dsn, u8 *ra,
        return 0;
 }
 
+void ieee80211s_update_metric(struct ieee80211_local *local,
+               struct sta_info *stainfo, struct sk_buff *skb)
+{
+       struct ieee80211_tx_info *txinfo = IEEE80211_SKB_CB(skb);
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+       int failed;
+
+       if (!ieee80211_is_data(hdr->frame_control))
+               return;
+
+       failed = !(txinfo->flags & IEEE80211_TX_STAT_ACK);
+
+       /* moving average, scaled to 100 */
+       stainfo->fail_avg = ((80 * stainfo->fail_avg + 5) / 100 + 20 * failed);
+       if (stainfo->fail_avg > 95)
+               mesh_plink_broken(stainfo);
+}
+
 static u32 airtime_link_metric_get(struct ieee80211_local *local,
                                   struct sta_info *sta)
 {
index 007164919e0284d43719f3d44f03870bcf44e788..7c5142988bbb77f140d373e26414f9bd0dec31b7 100644 (file)
@@ -51,7 +51,6 @@
 #include <linux/random.h>
 #include <linux/ieee80211.h>
 #include <net/mac80211.h>
-#include "mesh.h"
 #include "rate.h"
 #include "rc80211_minstrel.h"
 
@@ -156,16 +155,12 @@ minstrel_tx_status(void *priv, struct ieee80211_supported_band *sband,
                   struct sk_buff *skb)
 {
        struct minstrel_sta_info *mi = priv_sta;
-       struct minstrel_priv *mp = (struct minstrel_priv *)priv;
        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
        struct ieee80211_tx_rate *ar = info->status.rates;
-       struct ieee80211_local *local = hw_to_local(mp->hw);
-       struct sta_info *si;
        int i, ndx;
        int success;
 
        success = !!(info->flags & IEEE80211_TX_STAT_ACK);
-       si = sta_info_get(local, sta->addr);
 
        for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
                if (ar[i].idx < 0)
@@ -177,17 +172,8 @@ minstrel_tx_status(void *priv, struct ieee80211_supported_band *sband,
 
                mi->r[ndx].attempts += ar[i].count;
 
-               if ((i != IEEE80211_TX_MAX_RATES - 1) && (ar[i + 1].idx < 0)) {
+               if ((i != IEEE80211_TX_MAX_RATES - 1) && (ar[i + 1].idx < 0))
                        mi->r[ndx].success += success;
-                       if (si) {
-                               si->fail_avg = (18050 - mi->r[ndx].probability)
-                                       / 180;
-                               WARN_ON(si->fail_avg > 100);
-                               if (si->fail_avg == 100 &&
-                                       ieee80211_vif_is_mesh(&si->sdata->vif))
-                                       mesh_plink_broken(si);
-                       }
-               }
        }
 
        if ((info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) && (i >= 0))
index 8c053be9dc243b0ae4f1d778d6dfe9f23e875c1f..f6e25d7d957cb664e269daf92cbc1e36c180d9b6 100644 (file)
@@ -169,19 +169,9 @@ static void rate_control_pid_sample(struct rc_pid_info *pinfo,
         * still a good measurement and copy it. */
        if (unlikely(spinfo->tx_num_xmit == 0))
                pf = spinfo->last_pf;
-       else {
-               /* XXX: BAD HACK!!! */
-               struct sta_info *si = container_of(sta, struct sta_info, sta);
-
+       else
                pf = spinfo->tx_num_failed * 100 / spinfo->tx_num_xmit;
 
-               if (ieee80211_vif_is_mesh(&si->sdata->vif) && pf == 100)
-                       mesh_plink_broken(si);
-               pf <<= RC_PID_ARITH_SHIFT;
-               si->fail_avg = ((pf + (spinfo->last_pf << 3)) / 9)
-                                       >> RC_PID_ARITH_SHIFT;
-       }
-
        spinfo->tx_num_xmit = 0;
        spinfo->tx_num_failed = 0;
 
@@ -348,9 +338,6 @@ rate_control_pid_rate_init(void *priv, struct ieee80211_supported_band *sband,
        }
 
        spinfo->txrate_idx = rate_lowest_index(sband, sta);
-       /* HACK */
-       si = container_of(sta, struct sta_info, sta);
-       si->fail_avg = 0;
 }
 
 static void *rate_control_pid_alloc(struct ieee80211_hw *hw,