summaryrefslogtreecommitdiffstats
path: root/sys/net80211/ieee80211_mesh.c
diff options
context:
space:
mode:
authormonthadar <monthadar@FreeBSD.org>2012-05-01 15:47:30 +0000
committermonthadar <monthadar@FreeBSD.org>2012-05-01 15:47:30 +0000
commit661f0aa0b474eeb0e2188d7c75ce16dbe34a0229 (patch)
tree65098c124ba0f2f21be8fe1f8be7ee9c5ab321af /sys/net80211/ieee80211_mesh.c
parent6b5007d019c581519337942352d927a5c7de4f19 (diff)
downloadFreeBSD-src-661f0aa0b474eeb0e2188d7c75ce16dbe34a0229.zip
FreeBSD-src-661f0aa0b474eeb0e2188d7c75ce16dbe34a0229.tar.gz
Implemented so that Mesh forwarding information lifetime is dynamic.
* Introduced ieee80211_mesh_rt_update that updates a route with the maximum(lifetime left, new lifetime); * Modified ieee80211_mesh_route struct by adding a lock that will be used by both ieee80211_mesh_rt_update and precursor code (added in future commit); * Modified in ieee80211_hwmp.c HWMP code to use new ieee80211_mesh_rt_update; * Modified mesh_rt_flush_invalid to use new ieee80211_mesh_rt_update; * mesh_rt_flush also checks that lifetime == 0, this gives route discovery a change to complete; * Modified mesh_recv_mgmt case IEEE80211_FC0_SUBTYPE_BEACON: when ever we received a beacon from a neighbor we update route lifetime; Approved by: adrian
Diffstat (limited to 'sys/net80211/ieee80211_mesh.c')
-rw-r--r--sys/net80211/ieee80211_mesh.c112
1 files changed, 94 insertions, 18 deletions
diff --git a/sys/net80211/ieee80211_mesh.c b/sys/net80211/ieee80211_mesh.c
index de39607..3b0ff29 100644
--- a/sys/net80211/ieee80211_mesh.c
+++ b/sys/net80211/ieee80211_mesh.c
@@ -138,6 +138,10 @@ static const struct ieee80211_mesh_proto_metric mesh_metric_airtime = {
static struct ieee80211_mesh_proto_path mesh_proto_paths[4];
static struct ieee80211_mesh_proto_metric mesh_proto_metrics[4];
+#define RT_ENTRY_LOCK(rt) mtx_lock(&(rt)->rt_lock)
+#define RT_ENTRY_LOCK_ASSERT(rt) mtx_assert(&(rt)->rt_lock, MA_OWNED)
+#define RT_ENTRY_UNLOCK(rt) mtx_unlock(&(rt)->rt_lock)
+
#define MESH_RT_LOCK(ms) mtx_lock(&(ms)->ms_rt_lock)
#define MESH_RT_LOCK_ASSERT(ms) mtx_assert(&(ms)->ms_rt_lock, MA_OWNED)
#define MESH_RT_UNLOCK(ms) mtx_unlock(&(ms)->ms_rt_lock)
@@ -146,6 +150,9 @@ MALLOC_DEFINE(M_80211_MESH_PREQ, "80211preq", "802.11 MESH Path Request frame");
MALLOC_DEFINE(M_80211_MESH_PREP, "80211prep", "802.11 MESH Path Reply frame");
MALLOC_DEFINE(M_80211_MESH_PERR, "80211perr", "802.11 MESH Path Error frame");
+/* The longer one of the lifetime should be stored as new lifetime */
+#define MESH_ROUTE_LIFETIME_MAX(a, b) (a > b ? a : b)
+
MALLOC_DEFINE(M_80211_MESH_RT, "80211mesh", "802.11s routing table");
/*
@@ -183,7 +190,8 @@ mesh_rt_add_locked(struct ieee80211_mesh_state *ms,
if (rt != NULL) {
IEEE80211_ADDR_COPY(rt->rt_dest, dest);
rt->rt_priv = (void *)ALIGN(&rt[1]);
- rt->rt_crtime = ticks;
+ mtx_init(&rt->rt_lock, "MBSS_RT", "802.11s route entry", MTX_DEF);
+ rt->rt_updtime = ticks; /* create time */
TAILQ_INSERT_TAIL(&ms->ms_routes, rt, rt_next);
}
return rt;
@@ -221,6 +229,41 @@ ieee80211_mesh_rt_add(struct ieee80211vap *vap,
}
/*
+ * Update the route lifetime and returns the updated lifetime.
+ * If new_lifetime is zero and route is timedout it will be invalidated.
+ * new_lifetime is in msec
+ */
+int
+ieee80211_mesh_rt_update(struct ieee80211_mesh_route *rt, int new_lifetime)
+{
+ int timesince, now;
+ uint32_t lifetime = 0;
+
+ now = ticks;
+ RT_ENTRY_LOCK(rt);
+ timesince = ticks_to_msecs(now - rt->rt_updtime);
+ rt->rt_updtime = now;
+ if (timesince >= rt->rt_lifetime) {
+ if (new_lifetime != 0) {
+ rt->rt_lifetime = new_lifetime;
+ }
+ else {
+ rt->rt_flags &= ~IEEE80211_MESHRT_FLAGS_VALID;
+ rt->rt_lifetime = 0;
+ }
+ } else {
+ /* update what is left of lifetime */
+ rt->rt_lifetime = rt->rt_lifetime - timesince;
+ rt->rt_lifetime = MESH_ROUTE_LIFETIME_MAX(
+ new_lifetime, rt->rt_lifetime);
+ }
+ lifetime = rt->rt_lifetime;
+ RT_ENTRY_UNLOCK(rt);
+
+ return lifetime;
+}
+
+/*
* Add a proxy route (as needed) for the specified destination.
*/
void
@@ -271,6 +314,12 @@ static __inline void
mesh_rt_del(struct ieee80211_mesh_state *ms, struct ieee80211_mesh_route *rt)
{
TAILQ_REMOVE(&ms->ms_routes, rt, rt_next);
+ /*
+ * Grab the lock before destroying it, to be sure no one else
+ * is holding the route.
+ */
+ RT_ENTRY_LOCK(rt);
+ mtx_destroy(&rt->rt_lock);
free(rt, M_80211_MESH_RT);
}
@@ -335,8 +384,13 @@ mesh_rt_flush_invalid(struct ieee80211vap *vap)
return;
MESH_RT_LOCK(ms);
TAILQ_FOREACH_SAFE(rt, &ms->ms_routes, rt_next, next) {
+ ieee80211_mesh_rt_update(rt, 0);
+ /*
+ * NB: we check for lifetime == 0 so that we give a chance
+ * for route discovery to complete.
+ */
if ((rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID) == 0 &&
- ticks - rt->rt_crtime >= ms->ms_ppath->mpp_inact)
+ rt->rt_lifetime == 0)
mesh_rt_del(ms, rt);
}
MESH_RT_UNLOCK(ms);
@@ -1338,6 +1392,7 @@ mesh_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0, int subtype,
struct ieee80211_mesh_state *ms = vap->iv_mesh;
struct ieee80211com *ic = ni->ni_ic;
struct ieee80211_frame *wh;
+ struct ieee80211_mesh_route *rt;
uint8_t *frm, *efrm;
wh = mtod(m0, struct ieee80211_frame *);
@@ -1430,20 +1485,40 @@ mesh_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0, int subtype,
* XXX backoff on repeated failure
*/
if (ni != vap->iv_bss &&
- (ms->ms_flags & IEEE80211_MESHFLAGS_AP) &&
- ni->ni_mlstate == IEEE80211_NODE_MESH_IDLE) {
- uint16_t args[1];
-
- ni->ni_mlpid = mesh_generateid(vap);
- if (ni->ni_mlpid == 0)
- return;
- mesh_linkchange(ni, IEEE80211_NODE_MESH_OPENSNT);
- args[0] = ni->ni_mlpid;
- ieee80211_send_action(ni,
- IEEE80211_ACTION_CAT_SELF_PROT,
- IEEE80211_ACTION_MESHPEERING_OPEN, args);
- ni->ni_mlrcnt = 0;
- mesh_peer_timeout_setup(ni);
+ (ms->ms_flags & IEEE80211_MESHFLAGS_AP)) {
+ switch (ni->ni_mlstate) {
+ case IEEE80211_NODE_MESH_IDLE:
+ {
+ uint16_t args[1];
+
+ ni->ni_mlpid = mesh_generateid(vap);
+ if (ni->ni_mlpid == 0)
+ return;
+ mesh_linkchange(ni, IEEE80211_NODE_MESH_OPENSNT);
+ args[0] = ni->ni_mlpid;
+ ieee80211_send_action(ni,
+ IEEE80211_ACTION_CAT_SELF_PROT,
+ IEEE80211_ACTION_MESHPEERING_OPEN, args);
+ ni->ni_mlrcnt = 0;
+ mesh_peer_timeout_setup(ni);
+ break;
+ }
+ case IEEE80211_NODE_MESH_ESTABLISHED:
+ {
+ /*
+ * Valid beacon from a peer mesh STA
+ * bump TA lifetime
+ */
+ rt = ieee80211_mesh_rt_find(vap, wh->i_addr2);
+ if(rt != NULL) {
+ ieee80211_mesh_rt_update(rt,
+ ms->ms_ppath->mpp_inact);
+ }
+ break;
+ }
+ default:
+ break; /* ignore */
+ }
}
break;
}
@@ -2701,15 +2776,16 @@ mesh_ioctl_get80211(struct ieee80211vap *vap, struct ieee80211req *ireq)
break;
imr = (struct ieee80211req_mesh_route *)
(p + off);
- imr->imr_flags = rt->rt_flags;
IEEE80211_ADDR_COPY(imr->imr_dest,
rt->rt_dest);
IEEE80211_ADDR_COPY(imr->imr_nexthop,
rt->rt_nexthop);
imr->imr_metric = rt->rt_metric;
imr->imr_nhops = rt->rt_nhops;
- imr->imr_lifetime = rt->rt_lifetime;
+ imr->imr_lifetime =
+ ieee80211_mesh_rt_update(rt, 0);
imr->imr_lastmseq = rt->rt_lastmseq;
+ imr->imr_flags = rt->rt_flags; /* last */
off += sizeof(*imr);
}
MESH_RT_UNLOCK(ms);
OpenPOWER on IntegriCloud