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:
parent
6eb9b443f4
commit
b5df85a6fd
@ -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++;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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,8 +1485,10 @@ 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) {
|
||||
(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);
|
||||
@ -1444,6 +1501,24 @@ mesh_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0, int subtype,
|
||||
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);
|
||||
|
@ -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]);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user