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
This commit is contained in:
Monthadar Al Jaberi 2012-05-01 15:47:30 +00:00
parent 6eb9b443f4
commit b5df85a6fd
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=234877
4 changed files with 119 additions and 32 deletions

View File

@ -870,8 +870,10 @@ _db_show_mesh(const struct ieee80211_mesh_state *ms)
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++;
}
}

View File

@ -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, struct ieee80211_node *ni,
/* 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, struct ieee80211_node *ni,
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, struct ieee80211_node *ni,
}
}
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, struct ieee80211_node *ni,
}
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, struct ieee80211_node *ni,
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);

View File

@ -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;
@ -220,6 +228,41 @@ ieee80211_mesh_rt_add(struct ieee80211vap *vap,
return rt;
}
/*
* 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.
*/
@ -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];
(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);
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);

View File

@ -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 ieee80211vap *,
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]);