2011-08-25 01:22:06

by Thomas Pedersen

[permalink] [raw]
Subject: [PATCH 0/8] FIXUP: mesh gates

Since v1 of the mesh gate series was accidentally applied, revert the relevant
v1s and apply the v2s.

Javier Cardona (8):
Revert "{nl,cfg,mac}80211: let userspace make meshif mesh gate"
Revert "{nl,cfg,mac}80211: let userspace set RANN interval"
Revert "mac80211: mesh gate implementation"
Revert "mac80211: fix mpath timer NULL function"
mac80211: fix mpath timer removal
mac80211: mesh gate implementation
{nl,cfg,mac}80211: let userspace set RANN interval
{nl,cfg,mac}80211: let userspace make meshif mesh gate

net/mac80211/cfg.c | 8 ++++++++
net/mac80211/mesh.c | 4 ++--
net/mac80211/mesh_pathtbl.c | 10 ++++------
3 files changed, 14 insertions(+), 8 deletions(-)

--
1.7.4.1



2011-08-25 01:22:16

by Thomas Pedersen

[permalink] [raw]
Subject: [PATCH 5/8] mac80211: fix mpath timer removal

From: Javier Cardona <[email protected]>

Initialize mpath timers added to mpp_table.

Signed-off-by: Javier Cardona <[email protected]>
---

v2: - initialize timer instead of checking for NULL (Johannes)

net/mac80211/mesh_pathtbl.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c
index 41036a2..55ccd62 100644
--- a/net/mac80211/mesh_pathtbl.c
+++ b/net/mac80211/mesh_pathtbl.c
@@ -487,6 +487,7 @@ int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata)
new_mpath->flags = 0;
skb_queue_head_init(&new_mpath->frame_queue);
new_node->mpath = new_mpath;
+ init_timer(&new_mpath->timer);
new_mpath->exp_time = jiffies;
spin_lock_init(&new_mpath->state_lock);

--
1.7.4.1


2011-08-26 14:30:14

by John W. Linville

[permalink] [raw]
Subject: Re: [PATCH 0/8] FIXUP: mesh gates

On Thu, Aug 25, 2011 at 11:30:53AM -0700, Javier Cardona wrote:
> On Thu, Aug 25, 2011 at 4:45 AM, John W. Linville
> <[email protected]> wrote:
> > On Thu, Aug 25, 2011 at 12:21:29PM +0300, Kalle Valo wrote:
> >> Thomas Pedersen <[email protected]> writes:
> >>
> >> > Since v1 of the mesh gate series was accidentally applied, revert
> >> > the relevant v1s and apply the v2s.
> >>
> >> This looks ugly in the git history. IMHO it would be cleaner that you
> >> would do a diff between series v1 and v2 and submit that as a proper
> >> patch.
> >>
> >> But John might think otherwise, better to wait for his comment.
> >
> > That is how I would prefer it as well.
>
> As a general rule, should we treat patchsets sent to the list
> atomically? I.e. if there are objections to a few patches in the set,
> should we resubmit a v2 of the whole patchset?
> (Before asking I tried to find that info here:
> http://linuxwireless.org/en/developers/Documentation/SubmittingPatches
> . I'll be happy to update the wiki with your response if you think
> it's relevant)

In general, I would prefer to see the entire patchset reposted --
that leads to less confusion for me.

Hth!

John
--
John W. Linville Someday the world will need a hero, and you
[email protected] might be all we have. Be ready.

2011-08-25 01:22:20

by Thomas Pedersen

[permalink] [raw]
Subject: [PATCH 7/8] {nl,cfg,mac}80211: let userspace set RANN interval

From: Javier Cardona <[email protected]>

Allow userspace to set Root Announcement Interval for our mesh
interface. Also, RANN interval is now in proper units of TUs.

Signed-off-by: Javier Cardona <[email protected]>

---
v2: - use TU_TO_EXP_TIME macro (Johannes)

include/linux/nl80211.h | 4 ++++
include/net/cfg80211.h | 1 +
net/mac80211/cfg.c | 4 ++++
net/mac80211/debugfs_netdev.c | 3 +++
net/mac80211/mesh.c | 3 ++-
net/mac80211/mesh.h | 1 -
net/mac80211/mesh_hwmp.c | 8 ++++----
net/wireless/mesh.c | 2 ++
net/wireless/nl80211.c | 7 +++++++
9 files changed, 27 insertions(+), 6 deletions(-)

diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 89dec16..20353bb 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -1861,6 +1861,9 @@ enum nl80211_mntr_flags {
* @NL80211_MESHCONF_ELEMENT_TTL: specifies the value of TTL field set at a
* source mesh point for path selection elements.
*
+ * @NL80211_MESHCONF_HWMP_RANN_INTERVAL: The interval of time (in TUs) between
+ * root announcements are transmitted.
+ *
* @NL80211_MESHCONF_ATTR_MAX: highest possible mesh configuration attribute
*
* @__NL80211_MESHCONF_ATTR_AFTER_LAST: internal use
@@ -1882,6 +1885,7 @@ enum nl80211_meshconf_params {
NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME,
NL80211_MESHCONF_HWMP_ROOTMODE,
NL80211_MESHCONF_ELEMENT_TTL,
+ NL80211_MESHCONF_HWMP_RANN_INTERVAL,

/* keep last */
__NL80211_MESHCONF_ATTR_AFTER_LAST,
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 497e583..2d88f06 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -755,6 +755,7 @@ struct mesh_config {
u16 dot11MeshHWMPpreqMinInterval;
u16 dot11MeshHWMPnetDiameterTraversalTime;
u8 dot11MeshHWMPRootMode;
+ u16 dot11MeshHWMPRannInterval;
};

/**
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index c1fa577..9995c83 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1137,6 +1137,10 @@ static int ieee80211_update_mesh_config(struct wiphy *wiphy,
conf->dot11MeshHWMPRootMode = nconf->dot11MeshHWMPRootMode;
ieee80211_mesh_root_setup(ifmsh);
}
+ if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_RANN_INTERVAL, mask)) {
+ conf->dot11MeshHWMPRannInterval =
+ nconf->dot11MeshHWMPRannInterval;
+ }
return 0;
}

diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c
index 75ece3d..bac9443 100644
--- a/net/mac80211/debugfs_netdev.c
+++ b/net/mac80211/debugfs_netdev.c
@@ -372,6 +372,8 @@ IEEE80211_IF_FILE(min_discovery_timeout,
u.mesh.mshcfg.min_discovery_timeout, DEC);
IEEE80211_IF_FILE(dot11MeshHWMPRootMode,
u.mesh.mshcfg.dot11MeshHWMPRootMode, DEC);
+IEEE80211_IF_FILE(dot11MeshHWMPRannInterval,
+ u.mesh.mshcfg.dot11MeshHWMPRannInterval, DEC);
#endif


@@ -486,6 +488,7 @@ static void add_mesh_config(struct ieee80211_sub_if_data *sdata)
MESHPARAMS_ADD(path_refresh_time);
MESHPARAMS_ADD(min_discovery_timeout);
MESHPARAMS_ADD(dot11MeshHWMPRootMode);
+ MESHPARAMS_ADD(dot11MeshHWMPRannInterval);
#undef MESHPARAMS_ADD
}
#endif
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index e120fef..28ab510 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -537,7 +537,8 @@ static void ieee80211_mesh_rootpath(struct ieee80211_sub_if_data *sdata)

mesh_path_tx_root_frame(sdata);
mod_timer(&ifmsh->mesh_path_root_timer,
- round_jiffies(jiffies + IEEE80211_MESH_RANN_INTERVAL));
+ round_jiffies(TU_TO_EXP_TIME(
+ ifmsh->mshcfg.dot11MeshHWMPRannInterval)));
}

#ifdef CONFIG_PM
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h
index 9d9116e..2027207 100644
--- a/net/mac80211/mesh.h
+++ b/net/mac80211/mesh.h
@@ -175,7 +175,6 @@ struct mesh_rmc {

#define IEEE80211_MESH_PEER_INACTIVITY_LIMIT (1800 * HZ)
#define IEEE80211_MESH_HOUSEKEEPING_INTERVAL (60 * HZ)
-#define IEEE80211_MESH_RANN_INTERVAL (1 * HZ)

#define MESH_DEFAULT_BEACON_INTERVAL 1000 /* in 1024 us units */

diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index 7b517c4..ae3de75 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -695,7 +695,7 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata,
u8 ttl, flags, hopcount;
u8 *orig_addr;
u32 orig_sn, metric;
- u32 interval = cpu_to_le32(IEEE80211_MESH_RANN_INTERVAL);
+ u32 interval = ifmsh->mshcfg.dot11MeshHWMPRannInterval;
bool root_is_gate;

ttl = rann->rann_ttl;
@@ -743,7 +743,7 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata,
mesh_path_sel_frame_tx(MPATH_RANN, flags, orig_addr,
cpu_to_le32(orig_sn),
0, NULL, 0, broadcast_addr,
- hopcount, ttl, interval,
+ hopcount, ttl, cpu_to_le32(interval),
cpu_to_le32(metric + mpath->metric),
0, sdata);
mpath->sn = orig_sn;
@@ -1044,11 +1044,11 @@ void
mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
- u32 interval = cpu_to_le32(IEEE80211_MESH_RANN_INTERVAL);
+ u32 interval = ifmsh->mshcfg.dot11MeshHWMPRannInterval;

mesh_path_sel_frame_tx(MPATH_RANN, 0, sdata->vif.addr,
cpu_to_le32(++ifmsh->sn),
0, NULL, 0, broadcast_addr,
0, sdata->u.mesh.mshcfg.element_ttl,
- interval, 0, 0, sdata);
+ cpu_to_le32(interval), 0, 0, sdata);
}
diff --git a/net/wireless/mesh.c b/net/wireless/mesh.c
index 5c11608..b5a39d4 100644
--- a/net/wireless/mesh.c
+++ b/net/wireless/mesh.c
@@ -12,6 +12,7 @@
#define MESH_HOLD_T 100

#define MESH_PATH_TIMEOUT 5000
+#define MESH_RANN_INTERVAL 5000

/*
* Minimum interval between two consecutive PREQs originated by the same
@@ -49,6 +50,7 @@ const struct mesh_config default_mesh_config = {
.dot11MeshHWMPmaxPREQretries = MESH_MAX_PREQ_RETRIES,
.path_refresh_time = MESH_PATH_REFRESH_TIME,
.min_discovery_timeout = MESH_MIN_DISCOVERY_TIMEOUT,
+ .dot11MeshHWMPRannInterval = MESH_RANN_INTERVAL,
};

const struct mesh_setup default_mesh_setup = {
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 93ee888..bbf3d73 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -3035,6 +3035,8 @@ static int nl80211_get_mesh_config(struct sk_buff *skb,
cur_params.dot11MeshHWMPnetDiameterTraversalTime);
NLA_PUT_U8(msg, NL80211_MESHCONF_HWMP_ROOTMODE,
cur_params.dot11MeshHWMPRootMode);
+ NLA_PUT_U16(msg, NL80211_MESHCONF_HWMP_RANN_INTERVAL,
+ cur_params.dot11MeshHWMPRannInterval);
nla_nest_end(msg, pinfoattr);
genlmsg_end(msg, hdr);
return genlmsg_reply(msg, info);
@@ -3063,6 +3065,7 @@ static const struct nla_policy nl80211_meshconf_params_policy[NL80211_MESHCONF_A
[NL80211_MESHCONF_HWMP_PREQ_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 },
};

static const struct nla_policy
@@ -3141,6 +3144,10 @@ do {\
dot11MeshHWMPRootMode, mask,
NL80211_MESHCONF_HWMP_ROOTMODE,
nla_get_u8);
+ FILL_IN_MESH_PARAM_IF_SET(tb, cfg,
+ dot11MeshHWMPRannInterval, mask,
+ NL80211_MESHCONF_HWMP_RANN_INTERVAL,
+ nla_get_u16);
if (mask_out)
*mask_out = mask;

--
1.7.4.1


2011-08-25 01:22:14

by Thomas Pedersen

[permalink] [raw]
Subject: [PATCH 4/8] Revert "mac80211: fix mpath timer NULL function"

From: Javier Cardona <[email protected]>

This reverts commit 86d7f9f35dcc686d57465798201e678040916979.
---
net/mac80211/mesh_pathtbl.c | 6 ++----
1 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c
index bcf7fee..41036a2 100644
--- a/net/mac80211/mesh_pathtbl.c
+++ b/net/mac80211/mesh_pathtbl.c
@@ -619,8 +619,7 @@ static void mesh_path_node_reclaim(struct rcu_head *rp)
struct mpath_node *node = container_of(rp, struct mpath_node, rcu);
struct ieee80211_sub_if_data *sdata = node->mpath->sdata;

- if (node->mpath->timer.function)
- del_timer_sync(&node->mpath->timer);
+ del_timer_sync(&node->mpath->timer);
atomic_dec(&sdata->u.mesh.mpaths);
kfree(node->mpath);
kfree(node);
@@ -768,8 +767,7 @@ static void mesh_path_node_free(struct hlist_node *p, bool free_leafs)
mpath = node->mpath;
hlist_del_rcu(p);
if (free_leafs) {
- if (mpath->timer.function)
- del_timer_sync(&mpath->timer);
+ del_timer_sync(&mpath->timer);
kfree(mpath);
}
kfree(node);
--
1.7.4.1


2011-08-25 01:22:18

by Thomas Pedersen

[permalink] [raw]
Subject: [PATCH 6/8] mac80211: mesh gate implementation

From: Javier Cardona <[email protected]>

In this implementation, a mesh gate is a root node with a certain bit
set in its RANN flags. The mpath to this root node is marked as a path
to a gate, and added to our list of known gates for this if_mesh. Once a
path discovery process fails, we forward the unresolved frames to a
known gate. Thanks to Luis Rodriguez for refactoring and bug fix help.

Signed-off-by: Javier Cardona <[email protected]>

---
v2:
- fix uninitialized pointer

include/linux/ieee80211.h | 4 +
net/mac80211/ieee80211_i.h | 1 +
net/mac80211/mesh.c | 3 +-
net/mac80211/mesh.h | 11 ++
net/mac80211/mesh_hwmp.c | 41 +++++--
net/mac80211/mesh_pathtbl.c | 283 +++++++++++++++++++++++++++++++++++++++++++
6 files changed, 334 insertions(+), 9 deletions(-)

diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index 03cfbf3..37f95f2 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -633,6 +633,10 @@ struct ieee80211_rann_ie {
u32 rann_metric;
} __attribute__ ((packed));

+enum ieee80211_rann_flags {
+ RANN_FLAG_IS_GATE = 1 << 0,
+};
+
#define WLAN_SA_QUERY_TR_ID_LEN 2

struct ieee80211_mgmt {
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index ea74190..c204cee 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -514,6 +514,7 @@ struct ieee80211_if_mesh {
struct mesh_config mshcfg;
u32 mesh_seqnum;
bool accepting_plinks;
+ int num_gates;
const u8 *ie;
u8 ie_len;
enum {
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index ecdde6c..e120fef 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -545,7 +545,7 @@ void ieee80211_mesh_quiesce(struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;

- /* use atomic bitops in case both timers fire at the same time */
+ /* use atomic bitops in case all timers fire at the same time */

if (del_timer_sync(&ifmsh->housekeeping_timer))
set_bit(TMR_RUNNING_HK, &ifmsh->timers_running);
@@ -752,6 +752,7 @@ void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata)
ifmsh->accepting_plinks = true;
ifmsh->preq_id = 0;
ifmsh->sn = 0;
+ ifmsh->num_gates = 0;
atomic_set(&ifmsh->mpaths, 0);
mesh_rmc_init(sdata);
ifmsh->last_preq = jiffies;
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h
index 3c7d0f8..9d9116e 100644
--- a/net/mac80211/mesh.h
+++ b/net/mac80211/mesh.h
@@ -81,6 +81,7 @@ enum mesh_deferred_task_flags {
* @discovery_retries: number of discovery retries
* @flags: mesh path flags, as specified on &enum mesh_path_flags
* @state_lock: mesh path state lock
+ * @is_gate: the destination station of this path is a mesh gate
*
*
* The combination of dst and sdata is unique in the mesh path table. Since the
@@ -104,6 +105,7 @@ struct mesh_path {
u8 discovery_retries;
enum mesh_path_flags flags;
spinlock_t state_lock;
+ bool is_gate;
};

/**
@@ -120,6 +122,9 @@ struct mesh_path {
* buckets
* @mean_chain_len: maximum average length for the hash buckets' list, if it is
* reached, the table will grow
+ * @known_gates: list of known mesh gates and their mpaths by the station. The
+ * gate's mpath may or may not be resolved and active.
+ *
* rcu_head: RCU head to free the table
*/
struct mesh_table {
@@ -133,6 +138,8 @@ struct mesh_table {
int (*copy_node) (struct hlist_node *p, struct mesh_table *newtbl);
int size_order;
int mean_chain_len;
+ struct hlist_head *known_gates;
+ spinlock_t gates_lock;

struct rcu_head rcu_head;
};
@@ -236,6 +243,10 @@ void mesh_path_flush(struct ieee80211_sub_if_data *sdata);
void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata,
struct ieee80211_mgmt *mgmt, size_t len);
int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata);
+
+int mesh_path_add_gate(struct mesh_path *mpath);
+int mesh_path_send_to_gates(struct mesh_path *mpath);
+int mesh_gate_num(struct ieee80211_sub_if_data *sdata);
/* Mesh plinks */
void mesh_neighbour_update(u8 *hw_addr, u32 rates,
struct ieee80211_sub_if_data *sdata,
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index abd0347..7b517c4 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -696,6 +696,7 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata,
u8 *orig_addr;
u32 orig_sn, metric;
u32 interval = cpu_to_le32(IEEE80211_MESH_RANN_INTERVAL);
+ bool root_is_gate;

ttl = rann->rann_ttl;
if (ttl <= 1) {
@@ -704,12 +705,19 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata,
}
ttl--;
flags = rann->rann_flags;
+ root_is_gate = !!(flags & RANN_FLAG_IS_GATE);
orig_addr = rann->rann_addr;
orig_sn = rann->rann_seq;
hopcount = rann->rann_hopcount;
hopcount++;
metric = rann->rann_metric;
- mhwmp_dbg("received RANN from %pM\n", orig_addr);
+
+ /* Ignore our own RANNs */
+ if (memcmp(orig_addr, sdata->vif.addr, ETH_ALEN) == 0)
+ return;
+
+ mhwmp_dbg("received RANN from %pM (is_gate=%d)", orig_addr,
+ root_is_gate);

rcu_read_lock();
mpath = mesh_path_lookup(orig_addr, sdata);
@@ -721,9 +729,16 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata,
sdata->u.mesh.mshstats.dropped_frames_no_route++;
return;
}
- mesh_queue_preq(mpath,
- PREQ_Q_F_START | PREQ_Q_F_REFRESH);
}
+
+ if ((!(mpath->flags & (MESH_PATH_ACTIVE | MESH_PATH_RESOLVING)) ||
+ time_after(jiffies, mpath->exp_time - 1*HZ)) &&
+ !(mpath->flags & MESH_PATH_FIXED)) {
+ mhwmp_dbg("%s time to refresh root mpath %pM", sdata->name,
+ orig_addr);
+ mesh_queue_preq(mpath, PREQ_Q_F_START | PREQ_Q_F_REFRESH);
+ }
+
if (mpath->sn < orig_sn) {
mesh_path_sel_frame_tx(MPATH_RANN, flags, orig_addr,
cpu_to_le32(orig_sn),
@@ -733,6 +748,9 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata,
0, sdata);
mpath->sn = orig_sn;
}
+ if (root_is_gate)
+ mesh_path_add_gate(mpath);
+
rcu_read_unlock();
}

@@ -994,25 +1012,32 @@ void mesh_path_timer(unsigned long data)
{
struct mesh_path *mpath = (void *) data;
struct ieee80211_sub_if_data *sdata = mpath->sdata;
+ int ret;

if (sdata->local->quiescing)
return;

spin_lock_bh(&mpath->state_lock);
if (mpath->flags & MESH_PATH_RESOLVED ||
- (!(mpath->flags & MESH_PATH_RESOLVING)))
+ (!(mpath->flags & MESH_PATH_RESOLVING))) {
mpath->flags &= ~(MESH_PATH_RESOLVING | MESH_PATH_RESOLVED);
- else if (mpath->discovery_retries < max_preq_retries(sdata)) {
+ spin_unlock_bh(&mpath->state_lock);
+ } else if (mpath->discovery_retries < max_preq_retries(sdata)) {
++mpath->discovery_retries;
mpath->discovery_timeout *= 2;
+ spin_unlock_bh(&mpath->state_lock);
mesh_queue_preq(mpath, 0);
} else {
mpath->flags = 0;
mpath->exp_time = jiffies;
- mesh_path_flush_pending(mpath);
+ spin_unlock_bh(&mpath->state_lock);
+ if (!mpath->is_gate && mesh_gate_num(sdata) > 0) {
+ ret = mesh_path_send_to_gates(mpath);
+ if (ret)
+ mhwmp_dbg("no gate was reachable");
+ } else
+ mesh_path_flush_pending(mpath);
}
-
- spin_unlock_bh(&mpath->state_lock);
}

void
diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c
index 55ccd62..3c2bcb2 100644
--- a/net/mac80211/mesh_pathtbl.c
+++ b/net/mac80211/mesh_pathtbl.c
@@ -66,6 +66,8 @@ static inline struct mesh_table *resize_dereference_mpp_paths(void)
lockdep_is_held(&pathtbl_resize_lock));
}

+static int mesh_gate_add(struct mesh_table *tbl, struct mesh_path *mpath);
+
/*
* CAREFUL -- "tbl" must not be an expression,
* in particular not an rcu_dereference(), since
@@ -109,6 +111,7 @@ static struct mesh_table *mesh_table_alloc(int size_order)
sizeof(newtbl->hash_rnd));
for (i = 0; i <= newtbl->hash_mask; i++)
spin_lock_init(&newtbl->hashwlock[i]);
+ spin_lock_init(&newtbl->gates_lock);

return newtbl;
}
@@ -124,6 +127,7 @@ static void mesh_table_free(struct mesh_table *tbl, bool free_leafs)
{
struct hlist_head *mesh_hash;
struct hlist_node *p, *q;
+ struct mpath_node *gate;
int i;

mesh_hash = tbl->hash_buckets;
@@ -135,6 +139,17 @@ static void mesh_table_free(struct mesh_table *tbl, bool free_leafs)
}
spin_unlock_bh(&tbl->hashwlock[i]);
}
+ if (free_leafs) {
+ spin_lock_bh(&tbl->gates_lock);
+ hlist_for_each_entry_safe(gate, p, q,
+ tbl->known_gates, list) {
+ hlist_del(&gate->list);
+ kfree(gate);
+ }
+ kfree(tbl->known_gates);
+ spin_unlock_bh(&tbl->gates_lock);
+ }
+
__mesh_table_free(tbl);
}

@@ -152,6 +167,7 @@ static int mesh_table_grow(struct mesh_table *oldtbl,
newtbl->free_node = oldtbl->free_node;
newtbl->mean_chain_len = oldtbl->mean_chain_len;
newtbl->copy_node = oldtbl->copy_node;
+ newtbl->known_gates = oldtbl->known_gates;
atomic_set(&newtbl->entries, atomic_read(&oldtbl->entries));

oldhash = oldtbl->hash_buckets;
@@ -211,6 +227,111 @@ void mesh_path_assign_nexthop(struct mesh_path *mpath, struct sta_info *sta)
spin_unlock_irqrestore(&mpath->frame_queue.lock, flags);
}

+static void prepare_for_gate(struct sk_buff *skb, char *dst_addr,
+ struct mesh_path *gate_mpath)
+{
+ struct ieee80211_hdr *hdr;
+ struct ieee80211s_hdr *mshdr;
+ int mesh_hdrlen, hdrlen;
+ char *next_hop;
+
+ hdr = (struct ieee80211_hdr *) skb->data;
+ hdrlen = ieee80211_hdrlen(hdr->frame_control);
+ mshdr = (struct ieee80211s_hdr *) (skb->data + hdrlen);
+
+ if (!(mshdr->flags & MESH_FLAGS_AE)) {
+ /* size of the fixed part of the mesh header */
+ mesh_hdrlen = 6;
+
+ /* make room for the two extended addresses */
+ skb_push(skb, 2 * ETH_ALEN);
+ memmove(skb->data, hdr, hdrlen + mesh_hdrlen);
+
+ hdr = (struct ieee80211_hdr *) skb->data;
+
+ /* we preserve the previous mesh header and only add
+ * the new addreses */
+ mshdr = (struct ieee80211s_hdr *) (skb->data + hdrlen);
+ mshdr->flags = MESH_FLAGS_AE_A5_A6;
+ memcpy(mshdr->eaddr1, hdr->addr3, ETH_ALEN);
+ memcpy(mshdr->eaddr2, hdr->addr4, ETH_ALEN);
+ }
+
+ /* update next hop */
+ hdr = (struct ieee80211_hdr *) skb->data;
+ rcu_read_lock();
+ next_hop = rcu_dereference(gate_mpath->next_hop)->sta.addr;
+ memcpy(hdr->addr1, next_hop, ETH_ALEN);
+ rcu_read_unlock();
+ memcpy(hdr->addr3, dst_addr, ETH_ALEN);
+}
+
+/**
+ *
+ * mesh_path_move_to_queue - Move or copy frames from one mpath queue to another
+ *
+ * This function is used to transfer or copy frames from an unresolved mpath to
+ * a gate mpath. The function also adds the Address Extension field and
+ * updates the next hop.
+ *
+ * If a frame already has an Address Extension field, only the next hop and
+ * destination addresses are updated.
+ *
+ * The gate mpath must be an active mpath with a valid mpath->next_hop.
+ *
+ * @mpath: An active mpath the frames will be sent to (i.e. the gate)
+ * @from_mpath: The failed mpath
+ * @copy: When true, copy all the frames to the new mpath queue. When false,
+ * move them.
+ */
+static void mesh_path_move_to_queue(struct mesh_path *gate_mpath,
+ struct mesh_path *from_mpath,
+ bool copy)
+{
+ struct sk_buff *skb, *cp_skb = NULL;
+ struct sk_buff_head gateq, failq;
+ unsigned long flags;
+ int num_skbs;
+
+ BUG_ON(gate_mpath == from_mpath);
+ BUG_ON(!gate_mpath->next_hop);
+
+ __skb_queue_head_init(&gateq);
+ __skb_queue_head_init(&failq);
+
+ spin_lock_irqsave(&from_mpath->frame_queue.lock, flags);
+ skb_queue_splice_init(&from_mpath->frame_queue, &failq);
+ spin_unlock_irqrestore(&from_mpath->frame_queue.lock, flags);
+
+ num_skbs = skb_queue_len(&failq);
+
+ while (num_skbs--) {
+ skb = __skb_dequeue(&failq);
+ if (copy)
+ cp_skb = skb_copy(skb, GFP_ATOMIC);
+
+ prepare_for_gate(skb, gate_mpath->dst, gate_mpath);
+ __skb_queue_tail(&gateq, skb);
+
+ if (copy && cp_skb)
+ __skb_queue_tail(&failq, cp_skb);
+ }
+
+ spin_lock_irqsave(&gate_mpath->frame_queue.lock, flags);
+ skb_queue_splice(&gateq, &gate_mpath->frame_queue);
+ mpath_dbg("Mpath queue for gate %pM has %d frames\n",
+ gate_mpath->dst,
+ skb_queue_len(&gate_mpath->frame_queue));
+ spin_unlock_irqrestore(&gate_mpath->frame_queue.lock, flags);
+
+ if (!copy)
+ return;
+
+ spin_lock_irqsave(&from_mpath->frame_queue.lock, flags);
+ skb_queue_splice(&failq, &from_mpath->frame_queue);
+ spin_unlock_irqrestore(&from_mpath->frame_queue.lock, flags);
+}
+

/**
* mesh_path_lookup - look up a path in the mesh path table
@@ -310,6 +431,109 @@ struct mesh_path *mesh_path_lookup_by_idx(int idx, struct ieee80211_sub_if_data
return NULL;
}

+static void mesh_gate_node_reclaim(struct rcu_head *rp)
+{
+ struct mpath_node *node = container_of(rp, struct mpath_node, rcu);
+ kfree(node);
+}
+
+/**
+ * mesh_gate_add - mark mpath as path to a mesh gate and add to known_gates
+ * @mesh_tbl: table which contains known_gates list
+ * @mpath: mpath to known mesh gate
+ *
+ * Returns: 0 on success
+ *
+ */
+static int mesh_gate_add(struct mesh_table *tbl, struct mesh_path *mpath)
+{
+ struct mpath_node *gate, *new_gate;
+ struct hlist_node *n;
+ int err;
+
+ rcu_read_lock();
+ tbl = rcu_dereference(tbl);
+
+ hlist_for_each_entry_rcu(gate, n, tbl->known_gates, list)
+ if (gate->mpath == mpath) {
+ err = -EEXIST;
+ goto err_rcu;
+ }
+
+ new_gate = kzalloc(sizeof(struct mpath_node), GFP_ATOMIC);
+ if (!new_gate) {
+ err = -ENOMEM;
+ goto err_rcu;
+ }
+
+ mpath->is_gate = true;
+ mpath->sdata->u.mesh.num_gates++;
+ new_gate->mpath = mpath;
+ spin_lock_bh(&tbl->gates_lock);
+ hlist_add_head_rcu(&new_gate->list, tbl->known_gates);
+ spin_unlock_bh(&tbl->gates_lock);
+ rcu_read_unlock();
+ mpath_dbg("Mesh path (%s): Recorded new gate: %pM. %d known gates\n",
+ mpath->sdata->name, mpath->dst,
+ mpath->sdata->u.mesh.num_gates);
+ return 0;
+err_rcu:
+ rcu_read_unlock();
+ return err;
+}
+
+/**
+ * mesh_gate_del - remove a mesh gate from the list of known gates
+ * @tbl: table which holds our list of known gates
+ * @mpath: gate mpath
+ *
+ * Returns: 0 on success
+ *
+ * Locking: must be called inside rcu_read_lock() section
+ */
+static int mesh_gate_del(struct mesh_table *tbl, struct mesh_path *mpath)
+{
+ struct mpath_node *gate;
+ struct hlist_node *p, *q;
+
+ tbl = rcu_dereference(tbl);
+
+ hlist_for_each_entry_safe(gate, p, q, tbl->known_gates, list)
+ if (gate->mpath == mpath) {
+ spin_lock_bh(&tbl->gates_lock);
+ hlist_del_rcu(&gate->list);
+ call_rcu(&gate->rcu, mesh_gate_node_reclaim);
+ spin_unlock_bh(&tbl->gates_lock);
+ mpath->sdata->u.mesh.num_gates--;
+ mpath->is_gate = false;
+ mpath_dbg("Mesh path (%s): Deleted gate: %pM. "
+ "%d known gates\n", mpath->sdata->name,
+ mpath->dst, mpath->sdata->u.mesh.num_gates);
+ break;
+ }
+
+ return 0;
+}
+
+/**
+ *
+ * mesh_path_add_gate - add the given mpath to a mesh gate to our path table
+ * @mpath: gate path to add to table
+ */
+int mesh_path_add_gate(struct mesh_path *mpath)
+{
+ return mesh_gate_add(mesh_paths, mpath);
+}
+
+/**
+ * mesh_gate_num - number of gates known to this interface
+ * @sdata: subif data
+ */
+int mesh_gate_num(struct ieee80211_sub_if_data *sdata)
+{
+ return sdata->u.mesh.num_gates;
+}
+
/**
* mesh_path_add - allocate and add a new path to the mesh path table
* @addr: destination address of the path (ETH_ALEN length)
@@ -655,6 +879,8 @@ int mesh_path_del(u8 *addr, struct ieee80211_sub_if_data *sdata)
if (mpath->sdata == sdata &&
memcmp(addr, mpath->dst, ETH_ALEN) == 0) {
spin_lock_bh(&mpath->state_lock);
+ if (mpath->is_gate)
+ mesh_gate_del(tbl, mpath);
mpath->flags |= MESH_PATH_RESOLVING;
hlist_del_rcu(&node->list);
call_rcu(&node->rcu, mesh_path_node_reclaim);
@@ -688,6 +914,58 @@ void mesh_path_tx_pending(struct mesh_path *mpath)
}

/**
+ * mesh_path_send_to_gates - sends pending frames to all known mesh gates
+ *
+ * @mpath: mesh path whose queue will be emptied
+ *
+ * If there is only one gate, the frames are transferred from the failed mpath
+ * queue to that gate's queue. If there are more than one gates, the frames
+ * are copied from each gate to the next. After frames are copied, the
+ * mpath queues are emptied onto the transmission queue.
+ */
+int mesh_path_send_to_gates(struct mesh_path *mpath)
+{
+ struct ieee80211_sub_if_data *sdata = mpath->sdata;
+ struct hlist_node *n;
+ struct mesh_table *tbl;
+ struct mesh_path *from_mpath = mpath;
+ struct mpath_node *gate = NULL;
+ bool copy = false;
+ struct hlist_head *known_gates;
+
+ rcu_read_lock();
+ tbl = rcu_dereference(mesh_paths);
+ known_gates = tbl->known_gates;
+ rcu_read_unlock();
+
+ if (!known_gates)
+ return -EHOSTUNREACH;
+
+ hlist_for_each_entry_rcu(gate, n, known_gates, list) {
+ if (gate->mpath->sdata != sdata)
+ continue;
+
+ if (gate->mpath->flags & MESH_PATH_ACTIVE) {
+ mpath_dbg("Forwarding to %pM\n", gate->mpath->dst);
+ mesh_path_move_to_queue(gate->mpath, from_mpath, copy);
+ from_mpath = gate->mpath;
+ copy = true;
+ } else {
+ mpath_dbg("Not forwarding %p\n", gate->mpath);
+ mpath_dbg("flags %x\n", gate->mpath->flags);
+ }
+ }
+
+ hlist_for_each_entry_rcu(gate, n, known_gates, list)
+ if (gate->mpath->sdata == sdata) {
+ mpath_dbg("Sending to %pM\n", gate->mpath->dst);
+ mesh_path_tx_pending(gate->mpath);
+ }
+
+ return (from_mpath == mpath) ? -EHOSTUNREACH : 0;
+}
+
+/**
* mesh_path_discard_frame - discard a frame whose path could not be resolved
*
* @skb: frame to discard
@@ -803,6 +1081,9 @@ int mesh_pathtbl_init(void)
tbl_path->free_node = &mesh_path_node_free;
tbl_path->copy_node = &mesh_path_node_copy;
tbl_path->mean_chain_len = MEAN_CHAIN_LEN;
+ tbl_path->known_gates = kzalloc(sizeof(struct hlist_head), GFP_ATOMIC);
+ INIT_HLIST_HEAD(tbl_path->known_gates);
+

tbl_mpp = mesh_table_alloc(INIT_PATHS_SIZE_ORDER);
if (!tbl_mpp) {
@@ -812,6 +1093,8 @@ int mesh_pathtbl_init(void)
tbl_mpp->free_node = &mesh_path_node_free;
tbl_mpp->copy_node = &mesh_path_node_copy;
tbl_mpp->mean_chain_len = MEAN_CHAIN_LEN;
+ tbl_mpp->known_gates = kzalloc(sizeof(struct hlist_head), GFP_ATOMIC);
+ INIT_HLIST_HEAD(tbl_mpp->known_gates);

/* Need no locking since this is during init */
RCU_INIT_POINTER(mesh_paths, tbl_path);
--
1.7.4.1


2011-08-25 13:15:15

by John W. Linville

[permalink] [raw]
Subject: Re: [PATCH 0/8] FIXUP: mesh gates

On Thu, Aug 25, 2011 at 12:21:29PM +0300, Kalle Valo wrote:
> Thomas Pedersen <[email protected]> writes:
>
> > Since v1 of the mesh gate series was accidentally applied, revert
> > the relevant v1s and apply the v2s.
>
> This looks ugly in the git history. IMHO it would be cleaner that you
> would do a diff between series v1 and v2 and submit that as a proper
> patch.
>
> But John might think otherwise, better to wait for his comment.

That is how I would prefer it as well.

John
--
John W. Linville Someday the world will need a hero, and you
[email protected] might be all we have. Be ready.

2011-08-25 09:21:44

by Kalle Valo

[permalink] [raw]
Subject: Re: [PATCH 0/8] FIXUP: mesh gates

Thomas Pedersen <[email protected]> writes:

> Since v1 of the mesh gate series was accidentally applied, revert
> the relevant v1s and apply the v2s.

This looks ugly in the git history. IMHO it would be cleaner that you
would do a diff between series v1 and v2 and submit that as a proper
patch.

But John might think otherwise, better to wait for his comment.

--
Kalle Valo

2011-08-25 01:22:09

by Thomas Pedersen

[permalink] [raw]
Subject: [PATCH 2/8] Revert "{nl,cfg,mac}80211: let userspace set RANN interval"

From: Javier Cardona <[email protected]>

This reverts commit 0507e159a2b590666982b53ecf6fb2843a5bb423.
---
include/linux/nl80211.h | 4 ----
include/net/cfg80211.h | 1 -
net/mac80211/cfg.c | 4 ----
net/mac80211/debugfs_netdev.c | 3 ---
net/mac80211/mesh.c | 3 +--
net/mac80211/mesh.h | 1 +
net/mac80211/mesh_hwmp.c | 8 ++++----
net/wireless/mesh.c | 2 --
net/wireless/nl80211.c | 7 -------
9 files changed, 6 insertions(+), 27 deletions(-)

diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 20353bb..89dec16 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -1861,9 +1861,6 @@ enum nl80211_mntr_flags {
* @NL80211_MESHCONF_ELEMENT_TTL: specifies the value of TTL field set at a
* source mesh point for path selection elements.
*
- * @NL80211_MESHCONF_HWMP_RANN_INTERVAL: The interval of time (in TUs) between
- * root announcements are transmitted.
- *
* @NL80211_MESHCONF_ATTR_MAX: highest possible mesh configuration attribute
*
* @__NL80211_MESHCONF_ATTR_AFTER_LAST: internal use
@@ -1885,7 +1882,6 @@ enum nl80211_meshconf_params {
NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME,
NL80211_MESHCONF_HWMP_ROOTMODE,
NL80211_MESHCONF_ELEMENT_TTL,
- NL80211_MESHCONF_HWMP_RANN_INTERVAL,

/* keep last */
__NL80211_MESHCONF_ATTR_AFTER_LAST,
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 2d88f06..497e583 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -755,7 +755,6 @@ struct mesh_config {
u16 dot11MeshHWMPpreqMinInterval;
u16 dot11MeshHWMPnetDiameterTraversalTime;
u8 dot11MeshHWMPRootMode;
- u16 dot11MeshHWMPRannInterval;
};

/**
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 9995c83..c1fa577 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1137,10 +1137,6 @@ static int ieee80211_update_mesh_config(struct wiphy *wiphy,
conf->dot11MeshHWMPRootMode = nconf->dot11MeshHWMPRootMode;
ieee80211_mesh_root_setup(ifmsh);
}
- if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_RANN_INTERVAL, mask)) {
- conf->dot11MeshHWMPRannInterval =
- nconf->dot11MeshHWMPRannInterval;
- }
return 0;
}

diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c
index bac9443..75ece3d 100644
--- a/net/mac80211/debugfs_netdev.c
+++ b/net/mac80211/debugfs_netdev.c
@@ -372,8 +372,6 @@ IEEE80211_IF_FILE(min_discovery_timeout,
u.mesh.mshcfg.min_discovery_timeout, DEC);
IEEE80211_IF_FILE(dot11MeshHWMPRootMode,
u.mesh.mshcfg.dot11MeshHWMPRootMode, DEC);
-IEEE80211_IF_FILE(dot11MeshHWMPRannInterval,
- u.mesh.mshcfg.dot11MeshHWMPRannInterval, DEC);
#endif


@@ -488,7 +486,6 @@ static void add_mesh_config(struct ieee80211_sub_if_data *sdata)
MESHPARAMS_ADD(path_refresh_time);
MESHPARAMS_ADD(min_discovery_timeout);
MESHPARAMS_ADD(dot11MeshHWMPRootMode);
- MESHPARAMS_ADD(dot11MeshHWMPRannInterval);
#undef MESHPARAMS_ADD
}
#endif
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index 1c4f53c..e120fef 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -537,8 +537,7 @@ static void ieee80211_mesh_rootpath(struct ieee80211_sub_if_data *sdata)

mesh_path_tx_root_frame(sdata);
mod_timer(&ifmsh->mesh_path_root_timer,
- round_jiffies(jiffies +
- usecs_to_jiffies(ifmsh->mshcfg.dot11MeshHWMPRannInterval * 1024)));
+ round_jiffies(jiffies + IEEE80211_MESH_RANN_INTERVAL));
}

#ifdef CONFIG_PM
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h
index 2027207..9d9116e 100644
--- a/net/mac80211/mesh.h
+++ b/net/mac80211/mesh.h
@@ -175,6 +175,7 @@ struct mesh_rmc {

#define IEEE80211_MESH_PEER_INACTIVITY_LIMIT (1800 * HZ)
#define IEEE80211_MESH_HOUSEKEEPING_INTERVAL (60 * HZ)
+#define IEEE80211_MESH_RANN_INTERVAL (1 * HZ)

#define MESH_DEFAULT_BEACON_INTERVAL 1000 /* in 1024 us units */

diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index ae3de75..7b517c4 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -695,7 +695,7 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata,
u8 ttl, flags, hopcount;
u8 *orig_addr;
u32 orig_sn, metric;
- u32 interval = ifmsh->mshcfg.dot11MeshHWMPRannInterval;
+ u32 interval = cpu_to_le32(IEEE80211_MESH_RANN_INTERVAL);
bool root_is_gate;

ttl = rann->rann_ttl;
@@ -743,7 +743,7 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata,
mesh_path_sel_frame_tx(MPATH_RANN, flags, orig_addr,
cpu_to_le32(orig_sn),
0, NULL, 0, broadcast_addr,
- hopcount, ttl, cpu_to_le32(interval),
+ hopcount, ttl, interval,
cpu_to_le32(metric + mpath->metric),
0, sdata);
mpath->sn = orig_sn;
@@ -1044,11 +1044,11 @@ void
mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
- u32 interval = ifmsh->mshcfg.dot11MeshHWMPRannInterval;
+ u32 interval = cpu_to_le32(IEEE80211_MESH_RANN_INTERVAL);

mesh_path_sel_frame_tx(MPATH_RANN, 0, sdata->vif.addr,
cpu_to_le32(++ifmsh->sn),
0, NULL, 0, broadcast_addr,
0, sdata->u.mesh.mshcfg.element_ttl,
- cpu_to_le32(interval), 0, 0, sdata);
+ interval, 0, 0, sdata);
}
diff --git a/net/wireless/mesh.c b/net/wireless/mesh.c
index b5a39d4..5c11608 100644
--- a/net/wireless/mesh.c
+++ b/net/wireless/mesh.c
@@ -12,7 +12,6 @@
#define MESH_HOLD_T 100

#define MESH_PATH_TIMEOUT 5000
-#define MESH_RANN_INTERVAL 5000

/*
* Minimum interval between two consecutive PREQs originated by the same
@@ -50,7 +49,6 @@ const struct mesh_config default_mesh_config = {
.dot11MeshHWMPmaxPREQretries = MESH_MAX_PREQ_RETRIES,
.path_refresh_time = MESH_PATH_REFRESH_TIME,
.min_discovery_timeout = MESH_MIN_DISCOVERY_TIMEOUT,
- .dot11MeshHWMPRannInterval = MESH_RANN_INTERVAL,
};

const struct mesh_setup default_mesh_setup = {
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index bbf3d73..93ee888 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -3035,8 +3035,6 @@ static int nl80211_get_mesh_config(struct sk_buff *skb,
cur_params.dot11MeshHWMPnetDiameterTraversalTime);
NLA_PUT_U8(msg, NL80211_MESHCONF_HWMP_ROOTMODE,
cur_params.dot11MeshHWMPRootMode);
- NLA_PUT_U16(msg, NL80211_MESHCONF_HWMP_RANN_INTERVAL,
- cur_params.dot11MeshHWMPRannInterval);
nla_nest_end(msg, pinfoattr);
genlmsg_end(msg, hdr);
return genlmsg_reply(msg, info);
@@ -3065,7 +3063,6 @@ static const struct nla_policy nl80211_meshconf_params_policy[NL80211_MESHCONF_A
[NL80211_MESHCONF_HWMP_PREQ_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 },
};

static const struct nla_policy
@@ -3144,10 +3141,6 @@ do {\
dot11MeshHWMPRootMode, mask,
NL80211_MESHCONF_HWMP_ROOTMODE,
nla_get_u8);
- FILL_IN_MESH_PARAM_IF_SET(tb, cfg,
- dot11MeshHWMPRannInterval, mask,
- NL80211_MESHCONF_HWMP_RANN_INTERVAL,
- nla_get_u16);
if (mask_out)
*mask_out = mask;

--
1.7.4.1


2011-08-25 01:22:12

by Thomas Pedersen

[permalink] [raw]
Subject: [PATCH 3/8] Revert "mac80211: mesh gate implementation"

From: Javier Cardona <[email protected]>

This reverts commit 5ee68e5b39de5cefecf147c58711f8ab01c21231.
---
include/linux/ieee80211.h | 4 -
net/mac80211/ieee80211_i.h | 1 -
net/mac80211/mesh.c | 3 +-
net/mac80211/mesh.h | 11 --
net/mac80211/mesh_hwmp.c | 41 ++-----
net/mac80211/mesh_pathtbl.c | 284 -------------------------------------------
6 files changed, 9 insertions(+), 335 deletions(-)

diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index 37f95f2..03cfbf3 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -633,10 +633,6 @@ struct ieee80211_rann_ie {
u32 rann_metric;
} __attribute__ ((packed));

-enum ieee80211_rann_flags {
- RANN_FLAG_IS_GATE = 1 << 0,
-};
-
#define WLAN_SA_QUERY_TR_ID_LEN 2

struct ieee80211_mgmt {
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index c204cee..ea74190 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -514,7 +514,6 @@ struct ieee80211_if_mesh {
struct mesh_config mshcfg;
u32 mesh_seqnum;
bool accepting_plinks;
- int num_gates;
const u8 *ie;
u8 ie_len;
enum {
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index e120fef..ecdde6c 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -545,7 +545,7 @@ void ieee80211_mesh_quiesce(struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;

- /* use atomic bitops in case all timers fire at the same time */
+ /* use atomic bitops in case both timers fire at the same time */

if (del_timer_sync(&ifmsh->housekeeping_timer))
set_bit(TMR_RUNNING_HK, &ifmsh->timers_running);
@@ -752,7 +752,6 @@ void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata)
ifmsh->accepting_plinks = true;
ifmsh->preq_id = 0;
ifmsh->sn = 0;
- ifmsh->num_gates = 0;
atomic_set(&ifmsh->mpaths, 0);
mesh_rmc_init(sdata);
ifmsh->last_preq = jiffies;
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h
index 9d9116e..3c7d0f8 100644
--- a/net/mac80211/mesh.h
+++ b/net/mac80211/mesh.h
@@ -81,7 +81,6 @@ enum mesh_deferred_task_flags {
* @discovery_retries: number of discovery retries
* @flags: mesh path flags, as specified on &enum mesh_path_flags
* @state_lock: mesh path state lock
- * @is_gate: the destination station of this path is a mesh gate
*
*
* The combination of dst and sdata is unique in the mesh path table. Since the
@@ -105,7 +104,6 @@ struct mesh_path {
u8 discovery_retries;
enum mesh_path_flags flags;
spinlock_t state_lock;
- bool is_gate;
};

/**
@@ -122,9 +120,6 @@ struct mesh_path {
* buckets
* @mean_chain_len: maximum average length for the hash buckets' list, if it is
* reached, the table will grow
- * @known_gates: list of known mesh gates and their mpaths by the station. The
- * gate's mpath may or may not be resolved and active.
- *
* rcu_head: RCU head to free the table
*/
struct mesh_table {
@@ -138,8 +133,6 @@ struct mesh_table {
int (*copy_node) (struct hlist_node *p, struct mesh_table *newtbl);
int size_order;
int mean_chain_len;
- struct hlist_head *known_gates;
- spinlock_t gates_lock;

struct rcu_head rcu_head;
};
@@ -243,10 +236,6 @@ void mesh_path_flush(struct ieee80211_sub_if_data *sdata);
void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata,
struct ieee80211_mgmt *mgmt, size_t len);
int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata);
-
-int mesh_path_add_gate(struct mesh_path *mpath);
-int mesh_path_send_to_gates(struct mesh_path *mpath);
-int mesh_gate_num(struct ieee80211_sub_if_data *sdata);
/* Mesh plinks */
void mesh_neighbour_update(u8 *hw_addr, u32 rates,
struct ieee80211_sub_if_data *sdata,
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index 7b517c4..abd0347 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -696,7 +696,6 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata,
u8 *orig_addr;
u32 orig_sn, metric;
u32 interval = cpu_to_le32(IEEE80211_MESH_RANN_INTERVAL);
- bool root_is_gate;

ttl = rann->rann_ttl;
if (ttl <= 1) {
@@ -705,19 +704,12 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata,
}
ttl--;
flags = rann->rann_flags;
- root_is_gate = !!(flags & RANN_FLAG_IS_GATE);
orig_addr = rann->rann_addr;
orig_sn = rann->rann_seq;
hopcount = rann->rann_hopcount;
hopcount++;
metric = rann->rann_metric;
-
- /* Ignore our own RANNs */
- if (memcmp(orig_addr, sdata->vif.addr, ETH_ALEN) == 0)
- return;
-
- mhwmp_dbg("received RANN from %pM (is_gate=%d)", orig_addr,
- root_is_gate);
+ mhwmp_dbg("received RANN from %pM\n", orig_addr);

rcu_read_lock();
mpath = mesh_path_lookup(orig_addr, sdata);
@@ -729,16 +721,9 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata,
sdata->u.mesh.mshstats.dropped_frames_no_route++;
return;
}
+ mesh_queue_preq(mpath,
+ PREQ_Q_F_START | PREQ_Q_F_REFRESH);
}
-
- if ((!(mpath->flags & (MESH_PATH_ACTIVE | MESH_PATH_RESOLVING)) ||
- time_after(jiffies, mpath->exp_time - 1*HZ)) &&
- !(mpath->flags & MESH_PATH_FIXED)) {
- mhwmp_dbg("%s time to refresh root mpath %pM", sdata->name,
- orig_addr);
- mesh_queue_preq(mpath, PREQ_Q_F_START | PREQ_Q_F_REFRESH);
- }
-
if (mpath->sn < orig_sn) {
mesh_path_sel_frame_tx(MPATH_RANN, flags, orig_addr,
cpu_to_le32(orig_sn),
@@ -748,9 +733,6 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata,
0, sdata);
mpath->sn = orig_sn;
}
- if (root_is_gate)
- mesh_path_add_gate(mpath);
-
rcu_read_unlock();
}

@@ -1012,32 +994,25 @@ void mesh_path_timer(unsigned long data)
{
struct mesh_path *mpath = (void *) data;
struct ieee80211_sub_if_data *sdata = mpath->sdata;
- int ret;

if (sdata->local->quiescing)
return;

spin_lock_bh(&mpath->state_lock);
if (mpath->flags & MESH_PATH_RESOLVED ||
- (!(mpath->flags & MESH_PATH_RESOLVING))) {
+ (!(mpath->flags & MESH_PATH_RESOLVING)))
mpath->flags &= ~(MESH_PATH_RESOLVING | MESH_PATH_RESOLVED);
- spin_unlock_bh(&mpath->state_lock);
- } else if (mpath->discovery_retries < max_preq_retries(sdata)) {
+ else if (mpath->discovery_retries < max_preq_retries(sdata)) {
++mpath->discovery_retries;
mpath->discovery_timeout *= 2;
- spin_unlock_bh(&mpath->state_lock);
mesh_queue_preq(mpath, 0);
} else {
mpath->flags = 0;
mpath->exp_time = jiffies;
- spin_unlock_bh(&mpath->state_lock);
- if (!mpath->is_gate && mesh_gate_num(sdata) > 0) {
- ret = mesh_path_send_to_gates(mpath);
- if (ret)
- mhwmp_dbg("no gate was reachable");
- } else
- mesh_path_flush_pending(mpath);
+ mesh_path_flush_pending(mpath);
}
+
+ spin_unlock_bh(&mpath->state_lock);
}

void
diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c
index 75e4b60..bcf7fee 100644
--- a/net/mac80211/mesh_pathtbl.c
+++ b/net/mac80211/mesh_pathtbl.c
@@ -66,8 +66,6 @@ static inline struct mesh_table *resize_dereference_mpp_paths(void)
lockdep_is_held(&pathtbl_resize_lock));
}

-static int mesh_gate_add(struct mesh_table *tbl, struct mesh_path *mpath);
-
/*
* CAREFUL -- "tbl" must not be an expression,
* in particular not an rcu_dereference(), since
@@ -111,7 +109,6 @@ static struct mesh_table *mesh_table_alloc(int size_order)
sizeof(newtbl->hash_rnd));
for (i = 0; i <= newtbl->hash_mask; i++)
spin_lock_init(&newtbl->hashwlock[i]);
- spin_lock_init(&newtbl->gates_lock);

return newtbl;
}
@@ -127,7 +124,6 @@ static void mesh_table_free(struct mesh_table *tbl, bool free_leafs)
{
struct hlist_head *mesh_hash;
struct hlist_node *p, *q;
- struct mpath_node *gate;
int i;

mesh_hash = tbl->hash_buckets;
@@ -139,17 +135,6 @@ static void mesh_table_free(struct mesh_table *tbl, bool free_leafs)
}
spin_unlock_bh(&tbl->hashwlock[i]);
}
- if (free_leafs) {
- spin_lock_bh(&tbl->gates_lock);
- hlist_for_each_entry_safe(gate, p, q,
- tbl->known_gates, list) {
- hlist_del(&gate->list);
- kfree(gate);
- }
- kfree(tbl->known_gates);
- spin_unlock_bh(&tbl->gates_lock);
- }
-
__mesh_table_free(tbl);
}

@@ -167,7 +152,6 @@ static int mesh_table_grow(struct mesh_table *oldtbl,
newtbl->free_node = oldtbl->free_node;
newtbl->mean_chain_len = oldtbl->mean_chain_len;
newtbl->copy_node = oldtbl->copy_node;
- newtbl->known_gates = oldtbl->known_gates;
atomic_set(&newtbl->entries, atomic_read(&oldtbl->entries));

oldhash = oldtbl->hash_buckets;
@@ -227,111 +211,6 @@ void mesh_path_assign_nexthop(struct mesh_path *mpath, struct sta_info *sta)
spin_unlock_irqrestore(&mpath->frame_queue.lock, flags);
}

-static void prepare_for_gate(struct sk_buff *skb, char *dst_addr,
- struct mesh_path *gate_mpath)
-{
- struct ieee80211_hdr *hdr;
- struct ieee80211s_hdr *mshdr;
- int mesh_hdrlen, hdrlen;
- char *next_hop;
-
- hdr = (struct ieee80211_hdr *) skb->data;
- hdrlen = ieee80211_hdrlen(hdr->frame_control);
- mshdr = (struct ieee80211s_hdr *) (skb->data + hdrlen);
-
- if (!(mshdr->flags & MESH_FLAGS_AE)) {
- /* size of the fixed part of the mesh header */
- mesh_hdrlen = 6;
-
- /* make room for the two extended addresses */
- skb_push(skb, 2 * ETH_ALEN);
- memmove(skb->data, hdr, hdrlen + mesh_hdrlen);
-
- hdr = (struct ieee80211_hdr *) skb->data;
-
- /* we preserve the previous mesh header and only add
- * the new addreses */
- mshdr = (struct ieee80211s_hdr *) (skb->data + hdrlen);
- mshdr->flags = MESH_FLAGS_AE_A5_A6;
- memcpy(mshdr->eaddr1, hdr->addr3, ETH_ALEN);
- memcpy(mshdr->eaddr2, hdr->addr4, ETH_ALEN);
- }
-
- /* update next hop */
- hdr = (struct ieee80211_hdr *) skb->data;
- rcu_read_lock();
- next_hop = rcu_dereference(gate_mpath->next_hop)->sta.addr;
- memcpy(hdr->addr1, next_hop, ETH_ALEN);
- rcu_read_unlock();
- memcpy(hdr->addr3, dst_addr, ETH_ALEN);
-}
-
-/**
- *
- * mesh_path_move_to_queue - Move or copy frames from one mpath queue to another
- *
- * This function is used to transfer or copy frames from an unresolved mpath to
- * a gate mpath. The function also adds the Address Extension field and
- * updates the next hop.
- *
- * If a frame already has an Address Extension field, only the next hop and
- * destination addresses are updated.
- *
- * The gate mpath must be an active mpath with a valid mpath->next_hop.
- *
- * @mpath: An active mpath the frames will be sent to (i.e. the gate)
- * @from_mpath: The failed mpath
- * @copy: When true, copy all the frames to the new mpath queue. When false,
- * move them.
- */
-static void mesh_path_move_to_queue(struct mesh_path *gate_mpath,
- struct mesh_path *from_mpath,
- bool copy)
-{
- struct sk_buff *skb, *cp_skb;
- struct sk_buff_head gateq, failq;
- unsigned long flags;
- int num_skbs;
-
- BUG_ON(gate_mpath == from_mpath);
- BUG_ON(!gate_mpath->next_hop);
-
- __skb_queue_head_init(&gateq);
- __skb_queue_head_init(&failq);
-
- spin_lock_irqsave(&from_mpath->frame_queue.lock, flags);
- skb_queue_splice_init(&from_mpath->frame_queue, &failq);
- spin_unlock_irqrestore(&from_mpath->frame_queue.lock, flags);
-
- num_skbs = skb_queue_len(&failq);
-
- while (num_skbs--) {
- skb = __skb_dequeue(&failq);
- if (copy)
- cp_skb = skb_copy(skb, GFP_ATOMIC);
-
- prepare_for_gate(skb, gate_mpath->dst, gate_mpath);
- __skb_queue_tail(&gateq, skb);
-
- if (copy && cp_skb)
- __skb_queue_tail(&failq, cp_skb);
- }
-
- spin_lock_irqsave(&gate_mpath->frame_queue.lock, flags);
- skb_queue_splice(&gateq, &gate_mpath->frame_queue);
- mpath_dbg("Mpath queue for gate %pM has %d frames\n",
- gate_mpath->dst,
- skb_queue_len(&gate_mpath->frame_queue));
- spin_unlock_irqrestore(&gate_mpath->frame_queue.lock, flags);
-
- if (!copy)
- return;
-
- spin_lock_irqsave(&from_mpath->frame_queue.lock, flags);
- skb_queue_splice(&failq, &from_mpath->frame_queue);
- spin_unlock_irqrestore(&from_mpath->frame_queue.lock, flags);
-}
-

/**
* mesh_path_lookup - look up a path in the mesh path table
@@ -431,109 +310,6 @@ struct mesh_path *mesh_path_lookup_by_idx(int idx, struct ieee80211_sub_if_data
return NULL;
}

-static void mesh_gate_node_reclaim(struct rcu_head *rp)
-{
- struct mpath_node *node = container_of(rp, struct mpath_node, rcu);
- kfree(node);
-}
-
-/**
- * mesh_gate_add - mark mpath as path to a mesh gate and add to known_gates
- * @mesh_tbl: table which contains known_gates list
- * @mpath: mpath to known mesh gate
- *
- * Returns: 0 on success
- *
- */
-static int mesh_gate_add(struct mesh_table *tbl, struct mesh_path *mpath)
-{
- struct mpath_node *gate, *new_gate;
- struct hlist_node *n;
- int err;
-
- rcu_read_lock();
- tbl = rcu_dereference(tbl);
-
- hlist_for_each_entry_rcu(gate, n, tbl->known_gates, list)
- if (gate->mpath == mpath) {
- err = -EEXIST;
- goto err_rcu;
- }
-
- new_gate = kzalloc(sizeof(struct mpath_node), GFP_ATOMIC);
- if (!new_gate) {
- err = -ENOMEM;
- goto err_rcu;
- }
-
- mpath->is_gate = true;
- mpath->sdata->u.mesh.num_gates++;
- new_gate->mpath = mpath;
- spin_lock_bh(&tbl->gates_lock);
- hlist_add_head_rcu(&new_gate->list, tbl->known_gates);
- spin_unlock_bh(&tbl->gates_lock);
- rcu_read_unlock();
- mpath_dbg("Mesh path (%s): Recorded new gate: %pM. %d known gates\n",
- mpath->sdata->name, mpath->dst,
- mpath->sdata->u.mesh.num_gates);
- return 0;
-err_rcu:
- rcu_read_unlock();
- return err;
-}
-
-/**
- * mesh_gate_del - remove a mesh gate from the list of known gates
- * @tbl: table which holds our list of known gates
- * @mpath: gate mpath
- *
- * Returns: 0 on success
- *
- * Locking: must be called inside rcu_read_lock() section
- */
-static int mesh_gate_del(struct mesh_table *tbl, struct mesh_path *mpath)
-{
- struct mpath_node *gate;
- struct hlist_node *p, *q;
-
- tbl = rcu_dereference(tbl);
-
- hlist_for_each_entry_safe(gate, p, q, tbl->known_gates, list)
- if (gate->mpath == mpath) {
- spin_lock_bh(&tbl->gates_lock);
- hlist_del_rcu(&gate->list);
- call_rcu(&gate->rcu, mesh_gate_node_reclaim);
- spin_unlock_bh(&tbl->gates_lock);
- mpath->sdata->u.mesh.num_gates--;
- mpath->is_gate = false;
- mpath_dbg("Mesh path (%s): Deleted gate: %pM. "
- "%d known gates\n", mpath->sdata->name,
- mpath->dst, mpath->sdata->u.mesh.num_gates);
- break;
- }
-
- return 0;
-}
-
-/**
- *
- * mesh_path_add_gate - add the given mpath to a mesh gate to our path table
- * @mpath: gate path to add to table
- */
-int mesh_path_add_gate(struct mesh_path *mpath)
-{
- return mesh_gate_add(mesh_paths, mpath);
-}
-
-/**
- * mesh_gate_num - number of gates known to this interface
- * @sdata: subif data
- */
-int mesh_gate_num(struct ieee80211_sub_if_data *sdata)
-{
- return sdata->u.mesh.num_gates;
-}
-
/**
* mesh_path_add - allocate and add a new path to the mesh path table
* @addr: destination address of the path (ETH_ALEN length)
@@ -879,8 +655,6 @@ int mesh_path_del(u8 *addr, struct ieee80211_sub_if_data *sdata)
if (mpath->sdata == sdata &&
memcmp(addr, mpath->dst, ETH_ALEN) == 0) {
spin_lock_bh(&mpath->state_lock);
- if (mpath->is_gate)
- mesh_gate_del(tbl, mpath);
mpath->flags |= MESH_PATH_RESOLVING;
hlist_del_rcu(&node->list);
call_rcu(&node->rcu, mesh_path_node_reclaim);
@@ -914,58 +688,6 @@ void mesh_path_tx_pending(struct mesh_path *mpath)
}

/**
- * mesh_path_send_to_gates - sends pending frames to all known mesh gates
- *
- * @mpath: mesh path whose queue will be emptied
- *
- * If there is only one gate, the frames are transferred from the failed mpath
- * queue to that gate's queue. If there are more than one gates, the frames
- * are copied from each gate to the next. After frames are copied, the
- * mpath queues are emptied onto the transmission queue.
- */
-int mesh_path_send_to_gates(struct mesh_path *mpath)
-{
- struct ieee80211_sub_if_data *sdata = mpath->sdata;
- struct hlist_node *n;
- struct mesh_table *tbl;
- struct mesh_path *from_mpath = mpath;
- struct mpath_node *gate = NULL;
- bool copy = false;
- struct hlist_head *known_gates;
-
- rcu_read_lock();
- tbl = rcu_dereference(mesh_paths);
- known_gates = tbl->known_gates;
- rcu_read_unlock();
-
- if (!known_gates)
- return -EHOSTUNREACH;
-
- hlist_for_each_entry_rcu(gate, n, known_gates, list) {
- if (gate->mpath->sdata != sdata)
- continue;
-
- if (gate->mpath->flags & MESH_PATH_ACTIVE) {
- mpath_dbg("Forwarding to %pM\n", gate->mpath->dst);
- mesh_path_move_to_queue(gate->mpath, from_mpath, copy);
- from_mpath = gate->mpath;
- copy = true;
- } else {
- mpath_dbg("Not forwarding %p\n", gate->mpath);
- mpath_dbg("flags %x\n", gate->mpath->flags);
- }
- }
-
- hlist_for_each_entry_rcu(gate, n, known_gates, list)
- if (gate->mpath->sdata == sdata) {
- mpath_dbg("Sending to %pM\n", gate->mpath->dst);
- mesh_path_tx_pending(gate->mpath);
- }
-
- return (from_mpath == mpath) ? -EHOSTUNREACH : 0;
-}
-
-/**
* mesh_path_discard_frame - discard a frame whose path could not be resolved
*
* @skb: frame to discard
@@ -1082,9 +804,6 @@ int mesh_pathtbl_init(void)
tbl_path->free_node = &mesh_path_node_free;
tbl_path->copy_node = &mesh_path_node_copy;
tbl_path->mean_chain_len = MEAN_CHAIN_LEN;
- tbl_path->known_gates = kzalloc(sizeof(struct hlist_head), GFP_ATOMIC);
- INIT_HLIST_HEAD(tbl_path->known_gates);
-

tbl_mpp = mesh_table_alloc(INIT_PATHS_SIZE_ORDER);
if (!tbl_mpp) {
@@ -1094,9 +813,6 @@ int mesh_pathtbl_init(void)
tbl_mpp->free_node = &mesh_path_node_free;
tbl_mpp->copy_node = &mesh_path_node_copy;
tbl_mpp->mean_chain_len = MEAN_CHAIN_LEN;
- /* XXX: not needed */
- tbl_mpp->known_gates = kzalloc(sizeof(struct hlist_head), GFP_ATOMIC);
- INIT_HLIST_HEAD(tbl_mpp->known_gates);

/* Need no locking since this is during init */
RCU_INIT_POINTER(mesh_paths, tbl_path);
--
1.7.4.1


2011-08-25 01:22:22

by Thomas Pedersen

[permalink] [raw]
Subject: [PATCH 8/8] {nl,cfg,mac}80211: let userspace make meshif mesh gate

From: Javier Cardona <[email protected]>

Allow userspace to set NL80211_MESHCONF_GATE_ANNOUNCEMENTS attribute,
which will advertise this mesh node as being a mesh gate.
dot11MeshHWMPRootMode must be set as root announcements are used to
indicate we're a mesh gate. Set this if user forgot for now.

Signed-off-by: Javier Cardona <[email protected]>

---

v2: - make mesh gate a root node

include/linux/nl80211.h | 5 +++++
include/net/cfg80211.h | 5 +++++
net/mac80211/cfg.c | 12 ++++++++++++
net/mac80211/debugfs_netdev.c | 3 +++
net/mac80211/mesh_hwmp.c | 5 ++++-
net/wireless/mesh.c | 1 +
net/wireless/nl80211.c | 7 +++++++
7 files changed, 37 insertions(+), 1 deletions(-)

diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 20353bb..3769303 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -1864,6 +1864,10 @@ enum nl80211_mntr_flags {
* @NL80211_MESHCONF_HWMP_RANN_INTERVAL: The interval of time (in TUs) between
* root announcements are transmitted.
*
+ * @NL80211_MESHCONF_GATE_ANNOUNCEMENTS: Advertise that this mesh station has
+ * access to a broader network beyond the MBSS. This is done via Root
+ * Announcement frames.
+ *
* @NL80211_MESHCONF_ATTR_MAX: highest possible mesh configuration attribute
*
* @__NL80211_MESHCONF_ATTR_AFTER_LAST: internal use
@@ -1886,6 +1890,7 @@ enum nl80211_meshconf_params {
NL80211_MESHCONF_HWMP_ROOTMODE,
NL80211_MESHCONF_ELEMENT_TTL,
NL80211_MESHCONF_HWMP_RANN_INTERVAL,
+ NL80211_MESHCONF_GATE_ANNOUNCEMENTS,

/* keep last */
__NL80211_MESHCONF_ATTR_AFTER_LAST,
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 2d88f06..a37f264 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -756,6 +756,11 @@ struct mesh_config {
u16 dot11MeshHWMPnetDiameterTraversalTime;
u8 dot11MeshHWMPRootMode;
u16 dot11MeshHWMPRannInterval;
+ /* This is missnamed in draft 12.0: dot11MeshGateAnnouncementProtocol
+ * set to true only means that the station will announce others it's a
+ * mesh gate, but not necessarily using the gate announcement protocol.
+ * Still keeping the same nomenclature to be in sync with the spec. */
+ bool dot11MeshGateAnnouncementProtocol;
};

/**
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 9995c83..6ab67ab 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1137,6 +1137,18 @@ static int ieee80211_update_mesh_config(struct wiphy *wiphy,
conf->dot11MeshHWMPRootMode = nconf->dot11MeshHWMPRootMode;
ieee80211_mesh_root_setup(ifmsh);
}
+ if (_chg_mesh_attr(NL80211_MESHCONF_GATE_ANNOUNCEMENTS, mask)) {
+ /* our current gate announcement implementation rides on root
+ * announcements, so require this ifmsh to also be a root node
+ * */
+ if (nconf->dot11MeshGateAnnouncementProtocol &&
+ !conf->dot11MeshHWMPRootMode) {
+ conf->dot11MeshHWMPRootMode = 1;
+ ieee80211_mesh_root_setup(ifmsh);
+ }
+ conf->dot11MeshGateAnnouncementProtocol =
+ nconf->dot11MeshGateAnnouncementProtocol;
+ }
if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_RANN_INTERVAL, mask)) {
conf->dot11MeshHWMPRannInterval =
nconf->dot11MeshHWMPRannInterval;
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c
index bac9443..6e8eab7 100644
--- a/net/mac80211/debugfs_netdev.c
+++ b/net/mac80211/debugfs_netdev.c
@@ -372,6 +372,8 @@ IEEE80211_IF_FILE(min_discovery_timeout,
u.mesh.mshcfg.min_discovery_timeout, DEC);
IEEE80211_IF_FILE(dot11MeshHWMPRootMode,
u.mesh.mshcfg.dot11MeshHWMPRootMode, DEC);
+IEEE80211_IF_FILE(dot11MeshGateAnnouncementProtocol,
+ u.mesh.mshcfg.dot11MeshGateAnnouncementProtocol, DEC);
IEEE80211_IF_FILE(dot11MeshHWMPRannInterval,
u.mesh.mshcfg.dot11MeshHWMPRannInterval, DEC);
#endif
@@ -489,6 +491,7 @@ static void add_mesh_config(struct ieee80211_sub_if_data *sdata)
MESHPARAMS_ADD(min_discovery_timeout);
MESHPARAMS_ADD(dot11MeshHWMPRootMode);
MESHPARAMS_ADD(dot11MeshHWMPRannInterval);
+ MESHPARAMS_ADD(dot11MeshGateAnnouncementProtocol);
#undef MESHPARAMS_ADD
}
#endif
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index ae3de75..fd4f76a 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -1045,8 +1045,11 @@ mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
u32 interval = ifmsh->mshcfg.dot11MeshHWMPRannInterval;
+ u8 flags;

- mesh_path_sel_frame_tx(MPATH_RANN, 0, sdata->vif.addr,
+ flags = (ifmsh->mshcfg.dot11MeshGateAnnouncementProtocol)
+ ? RANN_FLAG_IS_GATE : 0;
+ mesh_path_sel_frame_tx(MPATH_RANN, flags, sdata->vif.addr,
cpu_to_le32(++ifmsh->sn),
0, NULL, 0, broadcast_addr,
0, sdata->u.mesh.mshcfg.element_ttl,
diff --git a/net/wireless/mesh.c b/net/wireless/mesh.c
index b5a39d4..4423e64 100644
--- a/net/wireless/mesh.c
+++ b/net/wireless/mesh.c
@@ -51,6 +51,7 @@ const struct mesh_config default_mesh_config = {
.path_refresh_time = MESH_PATH_REFRESH_TIME,
.min_discovery_timeout = MESH_MIN_DISCOVERY_TIMEOUT,
.dot11MeshHWMPRannInterval = MESH_RANN_INTERVAL,
+ .dot11MeshGateAnnouncementProtocol = false,
};

const struct mesh_setup default_mesh_setup = {
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index bbf3d73..57ecfa4 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -3037,6 +3037,8 @@ static int nl80211_get_mesh_config(struct sk_buff *skb,
cur_params.dot11MeshHWMPRootMode);
NLA_PUT_U16(msg, NL80211_MESHCONF_HWMP_RANN_INTERVAL,
cur_params.dot11MeshHWMPRannInterval);
+ NLA_PUT_U8(msg, NL80211_MESHCONF_GATE_ANNOUNCEMENTS,
+ cur_params.dot11MeshGateAnnouncementProtocol);
nla_nest_end(msg, pinfoattr);
genlmsg_end(msg, hdr);
return genlmsg_reply(msg, info);
@@ -3066,6 +3068,7 @@ static const struct nla_policy nl80211_meshconf_params_policy[NL80211_MESHCONF_A
[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 },
+ [NL80211_MESHCONF_GATE_ANNOUNCEMENTS] = { .type = NLA_U8 },
};

static const struct nla_policy
@@ -3148,6 +3151,10 @@ do {\
dot11MeshHWMPRannInterval, mask,
NL80211_MESHCONF_HWMP_RANN_INTERVAL,
nla_get_u16);
+ FILL_IN_MESH_PARAM_IF_SET(tb, cfg,
+ dot11MeshGateAnnouncementProtocol, mask,
+ NL80211_MESHCONF_GATE_ANNOUNCEMENTS,
+ nla_get_u8);
if (mask_out)
*mask_out = mask;

--
1.7.4.1


2011-08-25 18:31:13

by Javier Cardona

[permalink] [raw]
Subject: Re: [PATCH 0/8] FIXUP: mesh gates

On Thu, Aug 25, 2011 at 4:45 AM, John W. Linville
<[email protected]> wrote:
> On Thu, Aug 25, 2011 at 12:21:29PM +0300, Kalle Valo wrote:
>> Thomas Pedersen <[email protected]> writes:
>>
>> > Since v1 of the mesh gate series was accidentally applied, revert
>> > the relevant v1s and apply the v2s.
>>
>> This looks ugly in the git history. IMHO it would be cleaner that you
>> would do a diff between series v1 and v2 and submit that as a proper
>> patch.
>>
>> But John might think otherwise, better to wait for his comment.
>
> That is how I would prefer it as well.

As a general rule, should we treat patchsets sent to the list
atomically? I.e. if there are objections to a few patches in the set,
should we resubmit a v2 of the whole patchset?
(Before asking I tried to find that info here:
http://linuxwireless.org/en/developers/Documentation/SubmittingPatches
. I'll be happy to update the wiki with your response if you think
it's relevant)

Cheers,

Javier


--
Javier Cardona
cozybit Inc.
http://www.cozybit.com

2011-08-25 01:22:07

by Thomas Pedersen

[permalink] [raw]
Subject: [PATCH 1/8] Revert "{nl,cfg,mac}80211: let userspace make meshif mesh gate"

From: Javier Cardona <[email protected]>

This reverts commit 16dd7267f460739b3e29d984e73f05c5ffe2b142.
---
include/linux/nl80211.h | 5 -----
include/net/cfg80211.h | 5 -----
net/mac80211/cfg.c | 4 ----
net/mac80211/debugfs_netdev.c | 3 ---
net/mac80211/mesh_hwmp.c | 5 +----
net/wireless/mesh.c | 1 -
net/wireless/nl80211.c | 7 -------
7 files changed, 1 insertions(+), 29 deletions(-)

diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 3769303..20353bb 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -1864,10 +1864,6 @@ enum nl80211_mntr_flags {
* @NL80211_MESHCONF_HWMP_RANN_INTERVAL: The interval of time (in TUs) between
* root announcements are transmitted.
*
- * @NL80211_MESHCONF_GATE_ANNOUNCEMENTS: Advertise that this mesh station has
- * access to a broader network beyond the MBSS. This is done via Root
- * Announcement frames.
- *
* @NL80211_MESHCONF_ATTR_MAX: highest possible mesh configuration attribute
*
* @__NL80211_MESHCONF_ATTR_AFTER_LAST: internal use
@@ -1890,7 +1886,6 @@ enum nl80211_meshconf_params {
NL80211_MESHCONF_HWMP_ROOTMODE,
NL80211_MESHCONF_ELEMENT_TTL,
NL80211_MESHCONF_HWMP_RANN_INTERVAL,
- NL80211_MESHCONF_GATE_ANNOUNCEMENTS,

/* keep last */
__NL80211_MESHCONF_ATTR_AFTER_LAST,
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index a37f264..2d88f06 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -756,11 +756,6 @@ struct mesh_config {
u16 dot11MeshHWMPnetDiameterTraversalTime;
u8 dot11MeshHWMPRootMode;
u16 dot11MeshHWMPRannInterval;
- /* This is missnamed in draft 12.0: dot11MeshGateAnnouncementProtocol
- * set to true only means that the station will announce others it's a
- * mesh gate, but not necessarily using the gate announcement protocol.
- * Still keeping the same nomenclature to be in sync with the spec. */
- bool dot11MeshGateAnnouncementProtocol;
};

/**
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 7d17a91..9995c83 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1137,10 +1137,6 @@ static int ieee80211_update_mesh_config(struct wiphy *wiphy,
conf->dot11MeshHWMPRootMode = nconf->dot11MeshHWMPRootMode;
ieee80211_mesh_root_setup(ifmsh);
}
- if (_chg_mesh_attr(NL80211_MESHCONF_GATE_ANNOUNCEMENTS, mask)) {
- conf->dot11MeshGateAnnouncementProtocol =
- nconf->dot11MeshGateAnnouncementProtocol;
- }
if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_RANN_INTERVAL, mask)) {
conf->dot11MeshHWMPRannInterval =
nconf->dot11MeshHWMPRannInterval;
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c
index 6e8eab7..bac9443 100644
--- a/net/mac80211/debugfs_netdev.c
+++ b/net/mac80211/debugfs_netdev.c
@@ -372,8 +372,6 @@ IEEE80211_IF_FILE(min_discovery_timeout,
u.mesh.mshcfg.min_discovery_timeout, DEC);
IEEE80211_IF_FILE(dot11MeshHWMPRootMode,
u.mesh.mshcfg.dot11MeshHWMPRootMode, DEC);
-IEEE80211_IF_FILE(dot11MeshGateAnnouncementProtocol,
- u.mesh.mshcfg.dot11MeshGateAnnouncementProtocol, DEC);
IEEE80211_IF_FILE(dot11MeshHWMPRannInterval,
u.mesh.mshcfg.dot11MeshHWMPRannInterval, DEC);
#endif
@@ -491,7 +489,6 @@ static void add_mesh_config(struct ieee80211_sub_if_data *sdata)
MESHPARAMS_ADD(min_discovery_timeout);
MESHPARAMS_ADD(dot11MeshHWMPRootMode);
MESHPARAMS_ADD(dot11MeshHWMPRannInterval);
- MESHPARAMS_ADD(dot11MeshGateAnnouncementProtocol);
#undef MESHPARAMS_ADD
}
#endif
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index fd4f76a..ae3de75 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -1045,11 +1045,8 @@ mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
u32 interval = ifmsh->mshcfg.dot11MeshHWMPRannInterval;
- u8 flags;

- flags = (ifmsh->mshcfg.dot11MeshGateAnnouncementProtocol)
- ? RANN_FLAG_IS_GATE : 0;
- mesh_path_sel_frame_tx(MPATH_RANN, flags, sdata->vif.addr,
+ mesh_path_sel_frame_tx(MPATH_RANN, 0, sdata->vif.addr,
cpu_to_le32(++ifmsh->sn),
0, NULL, 0, broadcast_addr,
0, sdata->u.mesh.mshcfg.element_ttl,
diff --git a/net/wireless/mesh.c b/net/wireless/mesh.c
index 4423e64..b5a39d4 100644
--- a/net/wireless/mesh.c
+++ b/net/wireless/mesh.c
@@ -51,7 +51,6 @@ const struct mesh_config default_mesh_config = {
.path_refresh_time = MESH_PATH_REFRESH_TIME,
.min_discovery_timeout = MESH_MIN_DISCOVERY_TIMEOUT,
.dot11MeshHWMPRannInterval = MESH_RANN_INTERVAL,
- .dot11MeshGateAnnouncementProtocol = false,
};

const struct mesh_setup default_mesh_setup = {
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 57ecfa4..bbf3d73 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -3037,8 +3037,6 @@ static int nl80211_get_mesh_config(struct sk_buff *skb,
cur_params.dot11MeshHWMPRootMode);
NLA_PUT_U16(msg, NL80211_MESHCONF_HWMP_RANN_INTERVAL,
cur_params.dot11MeshHWMPRannInterval);
- NLA_PUT_U8(msg, NL80211_MESHCONF_GATE_ANNOUNCEMENTS,
- cur_params.dot11MeshGateAnnouncementProtocol);
nla_nest_end(msg, pinfoattr);
genlmsg_end(msg, hdr);
return genlmsg_reply(msg, info);
@@ -3068,7 +3066,6 @@ static const struct nla_policy nl80211_meshconf_params_policy[NL80211_MESHCONF_A
[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 },
- [NL80211_MESHCONF_GATE_ANNOUNCEMENTS] = { .type = NLA_U8 },
};

static const struct nla_policy
@@ -3151,10 +3148,6 @@ do {\
dot11MeshHWMPRannInterval, mask,
NL80211_MESHCONF_HWMP_RANN_INTERVAL,
nla_get_u16);
- FILL_IN_MESH_PARAM_IF_SET(tb, cfg,
- dot11MeshGateAnnouncementProtocol, mask,
- NL80211_MESHCONF_GATE_ANNOUNCEMENTS,
- nla_get_u8);
if (mask_out)
*mask_out = mask;

--
1.7.4.1