{nl,cfg,mac}80211: implement dot11MeshHWMPperrMinInterval
authorThomas Pedersen <thomas@cozybit.com>
Fri, 25 Nov 2011 01:15:24 +0000 (17:15 -0800)
committerJohn W. Linville <linville@tuxdriver.com>
Mon, 28 Nov 2011 19:44:06 +0000 (14:44 -0500)
As per 802.11mb 13.9.11.3

Signed-off-by: Thomas Pedersen <thomas@cozybit.com>
Signed-off-by: Javier Cardona <javier@cozybit.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
include/linux/nl80211.h
include/net/cfg80211.h
net/mac80211/cfg.c
net/mac80211/debugfs_netdev.c
net/mac80211/ieee80211_i.h
net/mac80211/mesh.c
net/mac80211/mesh_hwmp.c
net/wireless/mesh.c
net/wireless/nl80211.c

index 1fc0485..f51e3bf 100644 (file)
@@ -2094,6 +2094,10 @@ enum nl80211_mntr_flags {
  * access to a broader network beyond the MBSS.  This is done via Root
  * Announcement frames.
  *
+ * @NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL: The minimum interval of time (in
+ * TUs) during which a mesh STA can send only one Action frame containing a
+ * PERR element.
+ *
  * @NL80211_MESHCONF_ATTR_MAX: highest possible mesh configuration attribute
  *
  * @__NL80211_MESHCONF_ATTR_AFTER_LAST: internal use
@@ -2117,6 +2121,7 @@ enum nl80211_meshconf_params {
        NL80211_MESHCONF_ELEMENT_TTL,
        NL80211_MESHCONF_HWMP_RANN_INTERVAL,
        NL80211_MESHCONF_GATE_ANNOUNCEMENTS,
+       NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL,
 
        /* keep last */
        __NL80211_MESHCONF_ATTR_AFTER_LAST,
index 232d1a5..ce6236b 100644 (file)
@@ -782,6 +782,7 @@ struct mesh_config {
        u16 min_discovery_timeout;
        u32 dot11MeshHWMPactivePathTimeout;
        u16 dot11MeshHWMPpreqMinInterval;
+       u16 dot11MeshHWMPperrMinInterval;
        u16 dot11MeshHWMPnetDiameterTraversalTime;
        u8  dot11MeshHWMPRootMode;
        u16 dot11MeshHWMPRannInterval;
index 7ccba83..393b2a4 100644 (file)
@@ -1272,6 +1272,9 @@ static int ieee80211_update_mesh_config(struct wiphy *wiphy,
        if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL, mask))
                conf->dot11MeshHWMPpreqMinInterval =
                        nconf->dot11MeshHWMPpreqMinInterval;
+       if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL, mask))
+               conf->dot11MeshHWMPperrMinInterval =
+                       nconf->dot11MeshHWMPperrMinInterval;
        if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME,
                           mask))
                conf->dot11MeshHWMPnetDiameterTraversalTime =
index 9352819..8df2891 100644 (file)
@@ -405,6 +405,8 @@ IEEE80211_IF_FILE(dot11MeshHWMPactivePathTimeout,
                u.mesh.mshcfg.dot11MeshHWMPactivePathTimeout, DEC);
 IEEE80211_IF_FILE(dot11MeshHWMPpreqMinInterval,
                u.mesh.mshcfg.dot11MeshHWMPpreqMinInterval, DEC);
+IEEE80211_IF_FILE(dot11MeshHWMPperrMinInterval,
+               u.mesh.mshcfg.dot11MeshHWMPperrMinInterval, DEC);
 IEEE80211_IF_FILE(dot11MeshHWMPnetDiameterTraversalTime,
                u.mesh.mshcfg.dot11MeshHWMPnetDiameterTraversalTime, DEC);
 IEEE80211_IF_FILE(dot11MeshHWMPmaxPREQretries,
@@ -534,6 +536,7 @@ static void add_mesh_config(struct ieee80211_sub_if_data *sdata)
        MESHPARAMS_ADD(dot11MeshMaxPeerLinks);
        MESHPARAMS_ADD(dot11MeshHWMPactivePathTimeout);
        MESHPARAMS_ADD(dot11MeshHWMPpreqMinInterval);
+       MESHPARAMS_ADD(dot11MeshHWMPperrMinInterval);
        MESHPARAMS_ADD(dot11MeshHWMPnetDiameterTraversalTime);
        MESHPARAMS_ADD(dot11MeshHWMPmaxPREQretries);
        MESHPARAMS_ADD(path_refresh_time);
index 7a757a9..a785d61 100644 (file)
@@ -514,7 +514,9 @@ struct ieee80211_if_mesh {
        atomic_t mpaths;
        /* Timestamp of last SN update */
        unsigned long last_sn_update;
-       /* Timestamp of last SN sent */
+       /* Time when it's ok to send next PERR */
+       unsigned long next_perr;
+       /* Timestamp of last PREQ sent */
        unsigned long last_preq;
        struct mesh_rmc *rmc;
        spinlock_t mesh_preq_queue_lock;
index ee82d2f..c707c8b 100644 (file)
@@ -749,6 +749,7 @@ void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata)
        atomic_set(&ifmsh->mpaths, 0);
        mesh_rmc_init(sdata);
        ifmsh->last_preq = jiffies;
+       ifmsh->next_perr = jiffies;
        /* Allocate all mesh structures when creating the first mesh interface. */
        if (!mesh_allocated)
                ieee80211s_init();
index 208ba35..fe93386 100644 (file)
@@ -241,11 +241,15 @@ int mesh_path_error_tx(u8 ttl, u8 *target, __le32 target_sn,
 {
        struct ieee80211_local *local = sdata->local;
        struct sk_buff *skb;
+       struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
        struct ieee80211_mgmt *mgmt;
        u8 *pos, ie_len;
        int hdr_len = offsetof(struct ieee80211_mgmt, u.action.u.mesh_action) +
                      sizeof(mgmt->u.action.u.mesh_action);
 
+       if (time_before(jiffies, ifmsh->next_perr))
+               return -EAGAIN;
+
        skb = dev_alloc_skb(local->hw.extra_tx_headroom +
                            hdr_len +
                            2 + 15 /* PERR IE */);
@@ -290,6 +294,8 @@ int mesh_path_error_tx(u8 ttl, u8 *target, __le32 target_sn,
 
        /* see note in function header */
        prepare_frame_for_deferred_tx(sdata, skb);
+       ifmsh->next_perr = TU_TO_EXP_TIME(
+                                  ifmsh->mshcfg.dot11MeshHWMPperrMinInterval);
        ieee80211_add_pending_skb(local, skb);
        return 0;
 }
index b7b7868..8c550df 100644 (file)
@@ -20,6 +20,7 @@
  * interface
  */
 #define MESH_PREQ_MIN_INT      10
+#define MESH_PERR_MIN_INT      100
 #define MESH_DIAM_TRAVERSAL_TIME 50
 
 /*
@@ -47,6 +48,7 @@ const struct mesh_config default_mesh_config = {
        .dot11MeshMaxPeerLinks = MESH_MAX_ESTAB_PLINKS,
        .dot11MeshHWMPactivePathTimeout = MESH_PATH_TIMEOUT,
        .dot11MeshHWMPpreqMinInterval = MESH_PREQ_MIN_INT,
+       .dot11MeshHWMPperrMinInterval = MESH_PERR_MIN_INT,
        .dot11MeshHWMPnetDiameterTraversalTime = MESH_DIAM_TRAVERSAL_TIME,
        .dot11MeshHWMPmaxPREQretries = MESH_MAX_PREQ_RETRIES,
        .path_refresh_time = MESH_PATH_REFRESH_TIME,
index 5699c3b..0ee512b 100644 (file)
@@ -3195,6 +3195,8 @@ static int nl80211_get_mesh_config(struct sk_buff *skb,
                        cur_params.dot11MeshHWMPactivePathTimeout);
        NLA_PUT_U16(msg, NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL,
                        cur_params.dot11MeshHWMPpreqMinInterval);
+       NLA_PUT_U16(msg, NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL,
+                       cur_params.dot11MeshHWMPperrMinInterval);
        NLA_PUT_U16(msg, NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME,
                        cur_params.dot11MeshHWMPnetDiameterTraversalTime);
        NLA_PUT_U8(msg, NL80211_MESHCONF_HWMP_ROOTMODE,
@@ -3229,6 +3231,7 @@ static const struct nla_policy nl80211_meshconf_params_policy[NL80211_MESHCONF_A
        [NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT] = { .type = NLA_U16 },
        [NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT] = { .type = NLA_U32 },
        [NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL] = { .type = NLA_U16 },
+       [NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL] = { .type = NLA_U16 },
        [NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME] = { .type = NLA_U16 },
        [NL80211_MESHCONF_HWMP_ROOTMODE] = { .type = NLA_U8 },
        [NL80211_MESHCONF_HWMP_RANN_INTERVAL] = { .type = NLA_U16 },
@@ -3303,6 +3306,9 @@ do {\
        FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPpreqMinInterval,
                        mask, NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL,
                        nla_get_u16);
+       FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPperrMinInterval,
+                       mask, NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL,
+                       nla_get_u16);
        FILL_IN_MESH_PARAM_IF_SET(tb, cfg,
                        dot11MeshHWMPnetDiameterTraversalTime,
                        mask, NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME,