From owner-svn-src-all@FreeBSD.ORG Tue May 1 15:47:31 2012 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id 6EAC8106564A; Tue, 1 May 2012 15:47:31 +0000 (UTC) (envelope-from monthadar@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 589DC8FC0A; Tue, 1 May 2012 15:47:31 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q41FlVbA032644; Tue, 1 May 2012 15:47:31 GMT (envelope-from monthadar@svn.freebsd.org) Received: (from monthadar@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q41FlVbJ032639; Tue, 1 May 2012 15:47:31 GMT (envelope-from monthadar@svn.freebsd.org) Message-Id: <201205011547.q41FlVbJ032639@svn.freebsd.org> From: Monthadar Al Jaberi Date: Tue, 1 May 2012 15:47:31 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r234877 - head/sys/net80211 X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 01 May 2012 15:47:31 -0000 Author: monthadar Date: Tue May 1 15:47:30 2012 New Revision: 234877 URL: http://svn.freebsd.org/changeset/base/234877 Log: 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 Modified: head/sys/net80211/ieee80211_ddb.c head/sys/net80211/ieee80211_hwmp.c head/sys/net80211/ieee80211_mesh.c head/sys/net80211/ieee80211_mesh.h Modified: head/sys/net80211/ieee80211_ddb.c ============================================================================== --- head/sys/net80211/ieee80211_ddb.c Tue May 1 15:42:41 2012 (r234876) +++ head/sys/net80211/ieee80211_ddb.c Tue May 1 15:47:30 2012 (r234877) @@ -870,8 +870,10 @@ _db_show_mesh(const struct ieee80211_mes TAILQ_FOREACH(rt, &ms->ms_routes, rt_next) { db_printf("entry %d:\tdest: %6D nexthop: %6D metric: %u", i, rt->rt_dest, ":", rt->rt_nexthop, ":", rt->rt_metric); + db_printf("\tlifetime: %u lastseq: %u priv: %p\n", - rt->rt_lifetime, rt->rt_lastmseq, rt->rt_priv); + ieee80211_mesh_rt_update(rt, 0), + rt->rt_lastmseq, rt->rt_priv); i++; } } Modified: head/sys/net80211/ieee80211_hwmp.c ============================================================================== --- head/sys/net80211/ieee80211_hwmp.c Tue May 1 15:42:41 2012 (r234876) +++ head/sys/net80211/ieee80211_hwmp.c Tue May 1 15:47:30 2012 (r234877) @@ -143,9 +143,6 @@ typedef uint32_t ieee80211_hwmp_seq; #define HWMP_SEQ_GT(a, b) ((int32_t)((a)-(b)) > 0) #define HWMP_SEQ_GEQ(a, b) ((int32_t)((a)-(b)) >= 0) -/* The longer one of the lifetime should be stored as new lifetime */ -#define MESH_ROUTE_LIFETIME_MAX(a, b) (a > b ? a : b) - /* * Private extension of ieee80211_mesh_route. */ @@ -938,7 +935,7 @@ hwmp_recv_preq(struct ieee80211vap *vap, /* Data creation and update of forwarding information * according to Table 11C-8 for originator mesh STA. */ - if(HWMP_SEQ_GT(preq->preq_origseq, hrorig->hr_seq) || + if (HWMP_SEQ_GT(preq->preq_origseq, hrorig->hr_seq) || (HWMP_SEQ_EQ(preq->preq_origseq, hrorig->hr_seq) && preq->preq_metric < rtorig->rt_metric)) { hrorig->hr_seq = preq->preq_origseq; @@ -946,8 +943,7 @@ hwmp_recv_preq(struct ieee80211vap *vap, rtorig->rt_metric = preq->preq_metric + ms->ms_pmetric->mpm_metric(ni); rtorig->rt_nhops = preq->preq_hopcount + 1; - rtorig->rt_lifetime = MESH_ROUTE_LIFETIME_MAX( - preq->preq_lifetime, rtorig->rt_lifetime); + ieee80211_mesh_rt_update(rtorig, preq->preq_lifetime); /* path to orig is valid now */ rtorig->rt_flags |= IEEE80211_MESHRT_FLAGS_VALID; }else if(hrtarg != NULL && @@ -1124,7 +1120,7 @@ hwmp_recv_preq(struct ieee80211vap *vap, } } rt->rt_metric = preq->preq_metric; - rt->rt_lifetime = preq->preq_lifetime; + ieee80211_mesh_rt_update(rt, preq->preq_lifetime); hrorig = IEEE80211_MESH_ROUTE_PRIV(rt, struct ieee80211_hwmp_route); hrorig->hr_seq = preq->preq_origseq; @@ -1221,7 +1217,7 @@ hwmp_recv_prep(struct ieee80211vap *vap, } IEEE80211_ADDR_COPY(rt->rt_nexthop, wh->i_addr2); rt->rt_nhops = prep->prep_hopcount; - rt->rt_lifetime = prep->prep_lifetime; + ieee80211_mesh_rt_update(rt, prep->prep_lifetime); rt->rt_metric = prep->prep_metric; rt->rt_flags |= IEEE80211_MESHRT_FLAGS_VALID; IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni, @@ -1300,7 +1296,7 @@ hwmp_recv_prep(struct ieee80211vap *vap, rt->rt_metric, prep->prep_metric); IEEE80211_ADDR_COPY(rt->rt_nexthop, wh->i_addr2); rt->rt_nhops = prep->prep_hopcount + 1; - rt->rt_lifetime = prep->prep_lifetime; + ieee80211_mesh_rt_update(rt, prep->prep_lifetime); rt->rt_metric = metric; rt->rt_flags |= IEEE80211_MESHRT_FLAGS_VALID; } else { @@ -1594,8 +1590,9 @@ hwmp_discover(struct ieee80211vap *vap, if (hr->hr_origseq == 0) hr->hr_origseq = ++hs->hs_seq; rt->rt_metric = IEEE80211_MESHLMETRIC_INITIALVAL; - rt->rt_lifetime = - ticks_to_msecs(ieee80211_hwmp_pathtimeout); + /* XXX: special discovery timeout, larger lifetime? */ + ieee80211_mesh_rt_update(rt, + ticks_to_msecs(ieee80211_hwmp_pathtimeout)); /* XXX check preq retries */ sendpreq = 1; IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_HWMP, dest, @@ -1613,7 +1610,8 @@ hwmp_discover(struct ieee80211vap *vap, preq.preq_id = ++hs->hs_preqid; IEEE80211_ADDR_COPY(preq.preq_origaddr, vap->iv_myaddr); preq.preq_origseq = hr->hr_origseq; - preq.preq_lifetime = rt->rt_lifetime; + preq.preq_lifetime = + ticks_to_msecs(ieee80211_hwmp_pathtimeout); preq.preq_metric = rt->rt_metric; preq.preq_tcount = 1; IEEE80211_ADDR_COPY(PREQ_TADDR(0), dest); Modified: head/sys/net80211/ieee80211_mesh.c ============================================================================== --- head/sys/net80211/ieee80211_mesh.c Tue May 1 15:42:41 2012 (r234876) +++ head/sys/net80211/ieee80211_mesh.c Tue May 1 15:47:30 2012 (r234877) @@ -138,6 +138,10 @@ static const struct ieee80211_mesh_proto 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, "80211p 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 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 ieee80211va } /* + * 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 ieee80211va 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 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 * 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 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); Modified: head/sys/net80211/ieee80211_mesh.h ============================================================================== --- head/sys/net80211/ieee80211_mesh.h Tue May 1 15:42:41 2012 (r234876) +++ head/sys/net80211/ieee80211_mesh.h Tue May 1 15:47:30 2012 (r234877) @@ -409,9 +409,19 @@ MALLOC_DECLARE(M_80211_MESH_PREP); MALLOC_DECLARE(M_80211_MESH_PERR); MALLOC_DECLARE(M_80211_MESH_RT); +/* + * Basic forwarding information: + * o Destination MAC + * o Next-hop MAC + * o Precursor list (not implemented yet) + * o Path timeout + * The rest is part of the active Mesh path selection protocol. + * XXX: to be moved out later. + */ struct ieee80211_mesh_route { TAILQ_ENTRY(ieee80211_mesh_route) rt_next; - int rt_crtime; /* creation time */ + struct mtx rt_lock; /* fine grained route lock */ + int rt_updtime; /* last update time */ uint8_t rt_dest[IEEE80211_ADDR_LEN]; uint8_t rt_nexthop[IEEE80211_ADDR_LEN]; uint32_t rt_metric; /* path metric */ @@ -419,7 +429,7 @@ struct ieee80211_mesh_route { uint16_t rt_flags; #define IEEE80211_MESHRT_FLAGS_VALID 0x01 /* patch discovery complete */ #define IEEE80211_MESHRT_FLAGS_PROXY 0x02 /* proxy entry */ - uint32_t rt_lifetime; + uint32_t rt_lifetime; /* route timeout */ uint32_t rt_lastmseq; /* last seq# seen dest */ void *rt_priv; /* private data */ }; @@ -508,6 +518,7 @@ void ieee80211_mesh_rt_del(struct ieee8 void ieee80211_mesh_rt_flush(struct ieee80211vap *); void ieee80211_mesh_rt_flush_peer(struct ieee80211vap *, const uint8_t [IEEE80211_ADDR_LEN]); +int ieee80211_mesh_rt_update(struct ieee80211_mesh_route *rt, int); void ieee80211_mesh_proxy_check(struct ieee80211vap *, const uint8_t [IEEE80211_ADDR_LEN]);