From 243b95729ca5c07a39bdb7e327868460a6884474 Mon Sep 17 00:00:00 2001 From: rpaulo Date: Mon, 27 Jul 2009 14:22:09 +0000 Subject: Mesh fixes, namely: * don't clobber proxy entries * HWMP seq number processing, including discard of old frames * flush routing table entries based on nexthop * print route flags in ifconfig * more debugging messages and comments Proxy changes submitted by sam. Approved by: re (kib) --- sys/net80211/ieee80211_hwmp.c | 178 +++++++++++++++++++++++++----------------- 1 file changed, 106 insertions(+), 72 deletions(-) (limited to 'sys/net80211/ieee80211_hwmp.c') diff --git a/sys/net80211/ieee80211_hwmp.c b/sys/net80211/ieee80211_hwmp.c index 5ad0d41..040941e 100644 --- a/sys/net80211/ieee80211_hwmp.c +++ b/sys/net80211/ieee80211_hwmp.c @@ -137,15 +137,18 @@ static const uint8_t broadcastaddr[IEEE80211_ADDR_LEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; typedef uint32_t ieee80211_hwmp_seq; -#define IEEE80211_HWMP_SEQ_LEQ(a, b) ((int32_t)((a)-(b)) <= 0) -#define IEEE80211_HWMP_SEQ_GEQ(a, b) ((int32_t)((a)-(b)) >= 0) +#define HWMP_SEQ_LT(a, b) ((int32_t)((a)-(b)) < 0) +#define HWMP_SEQ_LEQ(a, b) ((int32_t)((a)-(b)) <= 0) +#define HWMP_SEQ_GT(a, b) ((int32_t)((a)-(b)) > 0) +#define HWMP_SEQ_GEQ(a, b) ((int32_t)((a)-(b)) >= 0) /* * Private extension of ieee80211_mesh_route. */ struct ieee80211_hwmp_route { - ieee80211_hwmp_seq hr_seq; /* HWMP sequence number */ - ieee80211_hwmp_seq hr_preqid; /* Last PREQ ID seen */ + ieee80211_hwmp_seq hr_seq; /* last HWMP seq seen from dst*/ + ieee80211_hwmp_seq hr_preqid; /* last PREQ ID seen from dst */ + ieee80211_hwmp_seq hr_targetseq; /* seq. no. on our latest PREQ*/ int hr_preqretries; }; struct ieee80211_hwmp_state { @@ -274,7 +277,6 @@ hwmp_newstate(struct ieee80211vap *vap, enum ieee80211_state ostate, int arg) __func__, ieee80211_state_name[ostate], ieee80211_state_name[nstate], arg); - /* Flush the table on RUN -> !RUN, e.g. interface down & up */ if (nstate != IEEE80211_S_RUN && ostate == IEEE80211_S_RUN) callout_drain(&hs->hs_roottimer); if (nstate == IEEE80211_S_RUN) @@ -656,8 +658,9 @@ hwmp_rootmode_cb(void *arg) IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, vap->iv_bss, "%s", "send broadcast PREQ"); - /* XXX check portal role */ preq.preq_flags = IEEE80211_MESHPREQ_FLAGS_AM; + if (ms->ms_flags & IEEE80211_MESHFLAGS_PORTAL) + preq.preq_flags |= IEEE80211_MESHPREQ_FLAGS_PR; if (hs->hs_rootmode == IEEE80211_HWMP_ROOTMODE_PROACTIVE) preq.preq_flags |= IEEE80211_MESHPREQ_FLAGS_PP; preq.preq_hopcount = 0; @@ -695,8 +698,8 @@ hwmp_rootmode_rann_cb(void *arg) IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, vap->iv_bss, "%s", "send broadcast RANN"); - /* XXX check portal role */ - rann.rann_flags = 0; + if (ms->ms_flags & IEEE80211_MESHFLAGS_PORTAL) + rann.rann_flags |= IEEE80211_MESHRANN_FLAGS_PR; rann.rann_hopcount = 0; rann.rann_ttl = ms->ms_ttl; IEEE80211_ADDR_COPY(rann.rann_addr, vap->iv_myaddr); @@ -717,7 +720,8 @@ hwmp_recv_preq(struct ieee80211vap *vap, struct ieee80211_node *ni, { struct ieee80211_mesh_state *ms = vap->iv_mesh; struct ieee80211_mesh_route *rt = NULL; - struct ieee80211_hwmp_route *hr; + struct ieee80211_mesh_route *rtorig = NULL; + struct ieee80211_hwmp_route *hrorig; struct ieee80211_hwmp_state *hs = vap->iv_hwmp; struct ieee80211_meshprep_ie prep; @@ -744,9 +748,26 @@ hwmp_recv_preq(struct ieee80211vap *vap, struct ieee80211_node *ni, preq->preq_origaddr, NULL, "%s", "not accepting PREQ"); return; } + rtorig = ieee80211_mesh_rt_find(vap, preq->preq_origaddr); + if (rtorig == NULL) + rtorig = ieee80211_mesh_rt_add(vap, preq->preq_origaddr); + hrorig = IEEE80211_MESH_ROUTE_PRIV(rtorig, struct ieee80211_hwmp_route); + /* + * Sequence number validation. + */ + if (HWMP_SEQ_LEQ(preq->preq_id, hrorig->hr_preqid) && + HWMP_SEQ_LEQ(preq->preq_origseq, hrorig->hr_seq)) { + IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni, + "discard PREQ from %s, old seq no %u <= %u", + ether_sprintf(preq->preq_origaddr), + preq->preq_origseq, hrorig->hr_seq); + return; + } + hrorig->hr_preqid = preq->preq_id; + hrorig->hr_seq = preq->preq_origseq; + /* * Check if the PREQ is addressed to us. - * XXX: check if this is part of a proxy address. */ if (IEEE80211_ADDR_EQ(vap->iv_myaddr, PREQ_TADDR(0))) { IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni, @@ -823,8 +844,6 @@ hwmp_recv_preq(struct ieee80211vap *vap, struct ieee80211_node *ni, } rt = ieee80211_mesh_rt_find(vap, PREQ_TADDR(0)); - /* XXX missing. Check for AE bit and update proxy information */ - /* * Forwarding and Intermediate reply for PREQs with 1 target. */ @@ -837,11 +856,6 @@ hwmp_recv_preq(struct ieee80211vap *vap, struct ieee80211_node *ni, */ if (rt != NULL && (rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID)) { - - hr = IEEE80211_MESH_ROUTE_PRIV(rt, - struct ieee80211_hwmp_route); - hr->hr_preqid = preq->preq_id; - hr->hr_seq = preq->preq_origseq; if (preq->preq_ttl > 1 && preq->preq_hopcount < hs->hs_maxhops) { IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni, @@ -880,13 +894,13 @@ hwmp_recv_preq(struct ieee80211vap *vap, struct ieee80211_node *ni, prep.prep_ttl = ms->ms_ttl; IEEE80211_ADDR_COPY(&prep.prep_targetaddr, preq->preq_origaddr); - prep.prep_targetseq = hr->hr_seq; + prep.prep_targetseq = hrorig->hr_seq; prep.prep_lifetime = preq->preq_lifetime; prep.prep_metric = rt->rt_metric + ms->ms_pmetric->mpm_metric(ni); IEEE80211_ADDR_COPY(&prep.prep_origaddr, PREQ_TADDR(0)); - prep.prep_origseq = hs->hs_seq++; + prep.prep_origseq = hrorig->hr_seq; hwmp_send_prep(ni, vap->iv_myaddr, broadcastaddr, &prep); } @@ -906,12 +920,12 @@ hwmp_recv_preq(struct ieee80211vap *vap, struct ieee80211_node *ni, return; } } - hr = IEEE80211_MESH_ROUTE_PRIV(rt, - struct ieee80211_hwmp_route); rt->rt_metric = preq->preq_metric; rt->rt_lifetime = preq->preq_lifetime; - hr->hr_seq = preq->preq_origseq; - hr->hr_preqid = preq->preq_id; + hrorig = IEEE80211_MESH_ROUTE_PRIV(rt, + struct ieee80211_hwmp_route); + hrorig->hr_seq = preq->preq_origseq; + hrorig->hr_preqid = preq->preq_id; IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni, "forward PREQ from %s", @@ -984,25 +998,6 @@ hwmp_recv_prep(struct ieee80211vap *vap, struct ieee80211_node *ni, IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni, "received PREP from %s", ether_sprintf(prep->prep_origaddr)); - /* - * If it's NOT for us, propagate the PREP. - */ - if (!IEEE80211_ADDR_EQ(vap->iv_myaddr, prep->prep_targetaddr) && - prep->prep_ttl > 1 && prep->prep_hopcount < hs->hs_maxhops) { - struct ieee80211_meshprep_ie pprep; /* propagated PREP */ - - IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni, - "propagate PREP from %s", - ether_sprintf(prep->prep_origaddr)); - - memcpy(&pprep, prep, sizeof(pprep)); - pprep.prep_hopcount += 1; - pprep.prep_ttl -= 1; - pprep.prep_metric += ms->ms_pmetric->mpm_metric(ni); - IEEE80211_ADDR_COPY(pprep.prep_origaddr, vap->iv_myaddr); - hwmp_send_prep(ni, vap->iv_myaddr, broadcastaddr, &pprep); - } - rt = ieee80211_mesh_rt_find(vap, prep->prep_origaddr); if (rt == NULL) { /* @@ -1022,48 +1017,86 @@ hwmp_recv_prep(struct ieee80211vap *vap, struct ieee80211_node *ni, rt->rt_lifetime = prep->prep_lifetime; rt->rt_metric = prep->prep_metric; rt->rt_flags |= IEEE80211_MESHRT_FLAGS_VALID; + IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni, + "add root path to %s nhops %d metric %d (PREP)", + ether_sprintf(prep->prep_origaddr), + rt->rt_nhops, rt->rt_metric); return; } return; } + /* + * Sequence number validation. + */ + hr = IEEE80211_MESH_ROUTE_PRIV(rt, struct ieee80211_hwmp_route); + if (HWMP_SEQ_LEQ(prep->prep_origseq, hr->hr_seq)) { + IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni, + "discard PREP from %s, old seq no %u <= %u", + ether_sprintf(prep->prep_origaddr), + prep->prep_origseq, hr->hr_seq); + return; + } + hr->hr_seq = prep->prep_origseq; + /* + * If it's NOT for us, propagate the PREP. + */ + if (!IEEE80211_ADDR_EQ(vap->iv_myaddr, prep->prep_targetaddr) && + prep->prep_ttl > 1 && prep->prep_hopcount < hs->hs_maxhops) { + struct ieee80211_meshprep_ie pprep; /* propagated PREP */ + + IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni, + "propagate PREP from %s", + ether_sprintf(prep->prep_origaddr)); + + memcpy(&pprep, prep, sizeof(pprep)); + pprep.prep_hopcount += 1; + pprep.prep_ttl -= 1; + pprep.prep_metric += ms->ms_pmetric->mpm_metric(ni); + IEEE80211_ADDR_COPY(pprep.prep_origaddr, vap->iv_myaddr); + hwmp_send_prep(ni, vap->iv_myaddr, broadcastaddr, &pprep); + } hr = IEEE80211_MESH_ROUTE_PRIV(rt, struct ieee80211_hwmp_route); - if (prep->prep_targetseq == hr->hr_seq) { - int useprep = 0; + if (rt->rt_flags & IEEE80211_MESHRT_FLAGS_PROXY) { + /* NB: never clobber a proxy entry */; + IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni, + "discard PREP for %s, route is marked PROXY", + ether_sprintf(prep->prep_origaddr)); + vap->iv_stats.is_hwmp_proxy++; + } else if (prep->prep_targetseq == hr->hr_targetseq) { /* * Check if we already have a path to this node. * If we do, check if this path reply contains a * better route. */ - if ((rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID) == 0) - useprep = 1; - else if (prep->prep_hopcount < rt->rt_nhops || - prep->prep_metric < rt->rt_metric) - useprep = 1; - if (useprep) { + if ((rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID) == 0 || + (prep->prep_hopcount < rt->rt_nhops || + prep->prep_metric < rt->rt_metric)) { + IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni, + "%s path to %s, hopcount %d:%d metric %d:%d", + rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID ? + "prefer" : "update", + ether_sprintf(prep->prep_origaddr), + rt->rt_nhops, prep->prep_hopcount, + rt->rt_metric, prep->prep_metric); IEEE80211_ADDR_COPY(rt->rt_nexthop, wh->i_addr2); rt->rt_nhops = prep->prep_hopcount; rt->rt_lifetime = prep->prep_lifetime; rt->rt_metric = prep->prep_metric; rt->rt_flags |= IEEE80211_MESHRT_FLAGS_VALID; + } else { + IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni, + "ignore PREP for %s, hopcount %d:%d metric %d:%d", + ether_sprintf(prep->prep_origaddr), + rt->rt_nhops, prep->prep_hopcount, + rt->rt_metric, prep->prep_metric); } } else { IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni, - "discard PREP from %s, wrong seqno %u != %u", + "discard PREP for %s, wrong seqno %u != %u", ether_sprintf(prep->prep_origaddr), prep->prep_targetseq, hr->hr_seq); vap->iv_stats.is_hwmp_wrongseq++; } - - /* - * XXX: If it's for us and the AE bit is set, update the - * proxy information table. - */ - - /* - * XXX: If it's NOT for us and the AE bit is set, - * update the proxy information table. - */ - /* * Check for frames queued awaiting path discovery. * XXX probably can tell exactly and avoid remove call @@ -1125,7 +1158,8 @@ hwmp_peerdown(struct ieee80211_node *ni) perr.perr_ndests = 1; IEEE80211_ADDR_COPY(PERR_DADDR(0), rt->rt_dest); PERR_DSEQ(0) = hr->hr_seq; - ieee80211_mesh_rt_del(vap, ni->ni_macaddr); + /* NB: flush everything passing through peer */ + ieee80211_mesh_rt_flush_peer(vap, ni->ni_macaddr); hwmp_send_perr(vap->iv_bss, vap->iv_myaddr, broadcastaddr, &perr); } #undef PERR_DADDR @@ -1160,8 +1194,9 @@ hwmp_recv_perr(struct ieee80211vap *vap, struct ieee80211_node *ni, continue; hr = IEEE80211_MESH_ROUTE_PRIV(rt, struct ieee80211_hwmp_route); - if (PERR_DSEQ(i) >= hr->hr_seq) { + if (HWMP_SEQ_GEQ(PERR_DSEQ(i), hr->hr_seq)) { ieee80211_mesh_rt_del(vap, rt->rt_dest); + ieee80211_mesh_rt_flush_peer(vap, rt->rt_dest); rt = NULL; forward = 1; } @@ -1174,7 +1209,8 @@ hwmp_recv_perr(struct ieee80211vap *vap, struct ieee80211_node *ni, IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni, "propagate PERR from %s", ether_sprintf(wh->i_addr2)); memcpy(&pperr, perr, sizeof(*perr)); - hwmp_send_perr(vap->iv_bss, vap->iv_myaddr, broadcastaddr, &pperr); + hwmp_send_perr(vap->iv_bss, vap->iv_myaddr, broadcastaddr, + &pperr); } } #undef PEER_DADDR @@ -1233,7 +1269,7 @@ hwmp_recv_rann(struct ieee80211vap *vap, struct ieee80211_node *ni, return; } hr = IEEE80211_MESH_ROUTE_PRIV(rt, struct ieee80211_hwmp_route); - if (rann->rann_seq > hr->hr_seq && rann->rann_ttl > 1 && + if (HWMP_SEQ_GT(rann->rann_seq, hr->hr_seq) && rann->rann_ttl > 1 && rann->rann_hopcount < hs->hs_maxhops && (ms->ms_flags & IEEE80211_MESHFLAGS_FWD)) { memcpy(&prann, rann, sizeof(prann)); @@ -1302,10 +1338,8 @@ hwmp_discover(struct ieee80211vap *vap, hr = IEEE80211_MESH_ROUTE_PRIV(rt, struct ieee80211_hwmp_route); if ((rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID) == 0) { - if (hr->hr_preqid == 0) { - hr->hr_seq = ++hs->hs_seq; - hr->hr_preqid = ++hs->hs_preqid; - } + if (hr->hr_targetseq == 0) + hr->hr_targetseq = ++hs->hs_seq; rt->rt_metric = IEEE80211_MESHLMETRIC_INITIALVAL; rt->rt_lifetime = ticks_to_msecs(ieee80211_hwmp_pathtimeout); @@ -1321,9 +1355,9 @@ hwmp_discover(struct ieee80211vap *vap, preq.preq_flags = 0; preq.preq_hopcount = 0; preq.preq_ttl = ms->ms_ttl; - preq.preq_id = hr->hr_preqid; + preq.preq_id = ++hs->hs_preqid; IEEE80211_ADDR_COPY(preq.preq_origaddr, vap->iv_myaddr); - preq.preq_origseq = hr->hr_seq; + preq.preq_origseq = hr->hr_targetseq; preq.preq_lifetime = rt->rt_lifetime; preq.preq_metric = rt->rt_metric; preq.preq_tcount = 1; -- cgit v1.1