From owner-svn-src-head@FreeBSD.ORG Mon Jul 27 14:22:09 2009 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 8D230106564A; Mon, 27 Jul 2009 14:22:09 +0000 (UTC) (envelope-from rpaulo@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 795E18FC0A; Mon, 27 Jul 2009 14:22:09 +0000 (UTC) (envelope-from rpaulo@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n6REM9NW002956; Mon, 27 Jul 2009 14:22:09 GMT (envelope-from rpaulo@svn.freebsd.org) Received: (from rpaulo@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n6REM9fR002950; Mon, 27 Jul 2009 14:22:09 GMT (envelope-from rpaulo@svn.freebsd.org) Message-Id: <200907271422.n6REM9fR002950@svn.freebsd.org> From: Rui Paulo Date: Mon, 27 Jul 2009 14:22:09 +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: r195908 - in head: sbin/ifconfig sys/net80211 X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 27 Jul 2009 14:22:10 -0000 Author: rpaulo Date: Mon Jul 27 14:22:09 2009 New Revision: 195908 URL: http://svn.freebsd.org/changeset/base/195908 Log: 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) Modified: head/sbin/ifconfig/ifieee80211.c head/sys/net80211/ieee80211_hwmp.c head/sys/net80211/ieee80211_ioctl.h head/sys/net80211/ieee80211_mesh.c head/sys/net80211/ieee80211_mesh.h Modified: head/sbin/ifconfig/ifieee80211.c ============================================================================== --- head/sbin/ifconfig/ifieee80211.c Mon Jul 27 13:51:55 2009 (r195907) +++ head/sbin/ifconfig/ifieee80211.c Mon Jul 27 14:22:09 2009 (r195908) @@ -3952,9 +3952,9 @@ list_regdomain(int s, int channelsalso) static void list_mesh(int s) { - int i; struct ieee80211req ireq; struct ieee80211req_mesh_route routes[128]; + struct ieee80211req_mesh_route *rt; (void) memset(&ireq, 0, sizeof(ireq)); (void) strncpy(ireq.i_name, name, sizeof(ireq.i_name)); @@ -3965,23 +3965,26 @@ list_mesh(int s) if (ioctl(s, SIOCG80211, &ireq) < 0) err(1, "unable to get the Mesh routing table"); - printf("%-17.17s %-17.17s %4s %4s %4s %6s\n" + printf("%-17.17s %-17.17s %4s %4s %4s %6s %s\n" , "DEST" , "NEXT HOP" , "HOPS" , "METRIC" , "LIFETIME" - , "MSEQ"); + , "MSEQ" + , "FLAGS"); - for (i = 0; i < ireq.i_len / sizeof(*routes); i++) { + for (rt = &routes[0]; rt - &routes[0] < ireq.i_len / sizeof(*rt); rt++){ printf("%s ", - ether_ntoa((const struct ether_addr *)routes[i].imr_dest)); - printf("%s %4u %4u %6u %6u\n", - ether_ntoa((const struct ether_addr *) - routes[i].imr_nexthop), - routes[i].imr_nhops, routes[i].imr_metric, - routes[i].imr_lifetime, - routes[i].imr_lastmseq); + ether_ntoa((const struct ether_addr *)rt->imr_dest)); + printf("%s %4u %4u %6u %6u %c%c\n", + ether_ntoa((const struct ether_addr *)rt->imr_nexthop), + rt->imr_nhops, rt->imr_metric, rt->imr_lifetime, + rt->imr_lastmseq, + (rt->imr_flags & IEEE80211_MESHRT_FLAGS_VALID) ? + 'V' : '!', + (rt->imr_flags & IEEE80211_MESHRT_FLAGS_PROXY) ? + 'P' : ' '); } } Modified: head/sys/net80211/ieee80211_hwmp.c ============================================================================== --- head/sys/net80211/ieee80211_hwmp.c Mon Jul 27 13:51:55 2009 (r195907) +++ head/sys/net80211/ieee80211_hwmp.c Mon Jul 27 14:22:09 2009 (r195908) @@ -137,15 +137,18 @@ static const uint8_t broadcastaddr[IEEE8 { 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, __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_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, 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, } 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, */ 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, 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, 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, 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, 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, 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, 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, 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; Modified: head/sys/net80211/ieee80211_ioctl.h ============================================================================== --- head/sys/net80211/ieee80211_ioctl.h Mon Jul 27 13:51:55 2009 (r195907) +++ head/sys/net80211/ieee80211_ioctl.h Mon Jul 27 14:22:09 2009 (r195908) @@ -240,8 +240,9 @@ struct ieee80211_stats { uint32_t is_mesh_rtaddfailed; /* route add failed */ uint32_t is_mesh_notproxy; /* dropped 'cuz not proxying */ uint32_t is_rx_badalign; /* dropped 'cuz misaligned */ + uint32_t is_hwmp_proxy; /* PREP for proxy route */ - uint32_t is_spare[12]; + uint32_t is_spare[11]; }; /* @@ -333,10 +334,13 @@ enum { }; struct ieee80211req_mesh_route { + uint8_t imr_flags; +#define IEEE80211_MESHRT_FLAGS_VALID 0x01 +#define IEEE80211_MESHRT_FLAGS_PROXY 0x02 uint8_t imr_dest[IEEE80211_ADDR_LEN]; uint8_t imr_nexthop[IEEE80211_ADDR_LEN]; uint16_t imr_nhops; - uint16_t imr_pad; + uint8_t imr_pad; uint32_t imr_metric; uint32_t imr_lifetime; uint32_t imr_lastmseq; Modified: head/sys/net80211/ieee80211_mesh.c ============================================================================== --- head/sys/net80211/ieee80211_mesh.c Mon Jul 27 13:51:55 2009 (r195907) +++ head/sys/net80211/ieee80211_mesh.c Mon Jul 27 14:22:09 2009 (r195908) @@ -236,6 +236,8 @@ ieee80211_mesh_proxy_check(struct ieee80 "%s", "unable to add proxy entry"); vap->iv_stats.is_mesh_rtaddfailed++; } else { + IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_MESH, dest, + "%s", "add proxy entry"); IEEE80211_ADDR_COPY(rt->rt_nexthop, vap->iv_myaddr); rt->rt_flags |= IEEE80211_MESHRT_FLAGS_VALID | IEEE80211_MESHRT_FLAGS_PROXY; @@ -301,6 +303,21 @@ ieee80211_mesh_rt_flush(struct ieee80211 MESH_RT_UNLOCK(ms); } +void +ieee80211_mesh_rt_flush_peer(struct ieee80211vap *vap, + const uint8_t peer[IEEE80211_ADDR_LEN]) +{ + struct ieee80211_mesh_state *ms = vap->iv_mesh; + struct ieee80211_mesh_route *rt, *next; + + MESH_RT_LOCK(ms); + TAILQ_FOREACH_SAFE(rt, &ms->ms_routes, rt_next, next) { + if (IEEE80211_ADDR_EQ(rt->rt_nexthop, peer)) + mesh_rt_del(ms, rt); + } + MESH_RT_UNLOCK(ms); +} + /* * Flush expired routing entries, i.e. those in invalid state for * some time. @@ -770,6 +787,7 @@ mesh_generateid(struct ieee80211vap *vap /* * Verifies if we already received this packet by checking its * sequence number. + * Returns 0 if the frame is to be accepted, 1 otherwise. */ static int mesh_checkpseq(struct ieee80211vap *vap, @@ -779,11 +797,16 @@ mesh_checkpseq(struct ieee80211vap *vap, rt = ieee80211_mesh_rt_find(vap, source); if (rt == NULL) { + rt = ieee80211_mesh_rt_add(vap, source); + if (rt == NULL) { + IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_MESH, source, + "%s", "add mcast route failed"); + vap->iv_stats.is_mesh_rtaddfailed++; + return 1; + } IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_MESH, source, "add mcast route, mesh seqno %d", seq); - rt = ieee80211_mesh_rt_add(vap, source); - if (rt != NULL) - rt->rt_lastmseq = seq; + rt->rt_lastmseq = seq; return 0; } if (IEEE80211_MESH_SEQ_GEQ(rt->rt_lastmseq, seq)) { @@ -1159,9 +1182,6 @@ mesh_input(struct ieee80211_node *ni, st goto out; } if (mesh_checkpseq(vap, addr, seq) != 0) { - IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_MESH, - addr, "data", "duplicate mesh seqno %u ttl %u", - seq, mc->mc_ttl); vap->iv_stats.is_rx_dup++; goto out; } @@ -2642,6 +2662,7 @@ 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, Modified: head/sys/net80211/ieee80211_mesh.h ============================================================================== --- head/sys/net80211/ieee80211_mesh.h Mon Jul 27 13:51:55 2009 (r195907) +++ head/sys/net80211/ieee80211_mesh.h Mon Jul 27 14:22:09 2009 (r195908) @@ -469,6 +469,8 @@ struct ieee80211_mesh_route * void ieee80211_mesh_rt_del(struct ieee80211vap *, const uint8_t [IEEE80211_ADDR_LEN]); void ieee80211_mesh_rt_flush(struct ieee80211vap *); +void ieee80211_mesh_rt_flush_peer(struct ieee80211vap *, + const uint8_t [IEEE80211_ADDR_LEN]); void ieee80211_mesh_proxy_check(struct ieee80211vap *, const uint8_t [IEEE80211_ADDR_LEN]);