svn commit: r195908 - in head: sbin/ifconfig sys/net80211

Rui Paulo rpaulo at FreeBSD.org
Mon Jul 27 14:22:10 UTC 2009


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]);
 


More information about the svn-src-head mailing list