[Zrouter-src-freebsd] ZRouter.org: push to FreeBSD HEAD tree

zrouter-src-freebsd at zrouter.org zrouter-src-freebsd at zrouter.org
Wed Feb 1 10:56:35 UTC 2012


details:   http://zrouter.org/hg/FreeBSD/head//rev/c769fd33bdf3
changeset: 309:c769fd33bdf3
user:      ray at terran.dlink.ua
date:      Wed Feb 01 11:32:14 2012 +0200
description:
Update sys/net80211

diffstat:

 head/sys/net80211/ieee80211.c      |    4 +-
 head/sys/net80211/ieee80211_dfs.c  |   84 ++++++++++--
 head/sys/net80211/ieee80211_dfs.h  |    8 +-
 head/sys/net80211/ieee80211_hwmp.c |  228 ++++++++++++++++++++++++------------
 4 files changed, 225 insertions(+), 99 deletions(-)

diffs (688 lines):

diff -r 7f838fc4de58 -r c769fd33bdf3 head/sys/net80211/ieee80211.c
--- a/head/sys/net80211/ieee80211.c	Wed Feb 01 11:31:56 2012 +0200
+++ b/head/sys/net80211/ieee80211.c	Wed Feb 01 11:32:14 2012 +0200
@@ -25,7 +25,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/net80211/ieee80211.c 228621 2011-12-17 10:23:17Z bschmidt $");
+__FBSDID("$FreeBSD: head/sys/net80211/ieee80211.c 230447 2012-01-22 05:30:29Z adrian $");
 
 /*
  * IEEE 802.11 generic handler
@@ -276,7 +276,7 @@
 	/* Create a taskqueue for all state changes */
 	ic->ic_tq = taskqueue_create("ic_taskq", M_WAITOK | M_ZERO,
 	    taskqueue_thread_enqueue, &ic->ic_tq);
-	taskqueue_start_threads(&ic->ic_tq, 1, PI_NET, "%s taskq",
+	taskqueue_start_threads(&ic->ic_tq, 1, PI_NET, "%s net80211 taskq",
 	    ifp->if_xname);
 	/*
 	 * Fill in 802.11 available channel set, mark all
diff -r 7f838fc4de58 -r c769fd33bdf3 head/sys/net80211/ieee80211_dfs.c
--- a/head/sys/net80211/ieee80211_dfs.c	Wed Feb 01 11:31:56 2012 +0200
+++ b/head/sys/net80211/ieee80211_dfs.c	Wed Feb 01 11:32:14 2012 +0200
@@ -25,7 +25,7 @@
 
 #include <sys/cdefs.h>
 #ifdef __FreeBSD__
-__FBSDID("$FreeBSD: head/sys/net80211/ieee80211_dfs.c 227331 2011-11-08 04:00:24Z adrian $");
+__FBSDID("$FreeBSD: head/sys/net80211/ieee80211_dfs.c 230793 2012-01-31 00:03:49Z adrian $");
 #endif
 
 /*
@@ -64,6 +64,28 @@
 	&ieee80211_cac_timeout, 0, "CAC timeout (secs)");
 #define	CAC_TIMEOUT	msecs_to_ticks(ieee80211_cac_timeout*1000)
 
+/*
+ DFS* In order to facilitate  debugging, a couple of operating
+ * modes aside from the default are needed.
+ *
+ * 0 - default CAC/NOL behaviour - ie, start CAC, place
+ *     channel on NOL list.
+ * 1 - send CAC, but don't change channel or add the channel
+ *     to the NOL list.
+ * 2 - just match on radar, don't send CAC or place channel in
+ *     the NOL list.
+ */
+static	int ieee80211_dfs_debug = DFS_DBG_NONE;
+
+/*
+ * This option must not be included in the default kernel
+ * as it allows users to plainly disable CAC/NOL handling.
+ */
+#ifdef	IEEE80211_DFS_DEBUG
+SYSCTL_INT(_net_wlan, OID_AUTO, dfs_debug, CTLFLAG_RW,
+	&ieee80211_dfs_debug, 0, "DFS debug behaviour");
+#endif
+
 static int
 null_set_quiet(struct ieee80211_node *ni, u_int8_t *quiet_elm)
 {
@@ -278,24 +300,44 @@
 	IEEE80211_LOCK_ASSERT(ic);
 
 	/*
-	 * Mark all entries with this frequency.  Notify user
-	 * space and arrange for notification when the radar
-	 * indication is cleared.  Then kick the NOL processing
-	 * thread if not already running.
+	 * If doing DFS debugging (mode 2), don't bother
+	 * running the rest of this function.
+	 *
+	 * Simply announce the presence of the radar and continue
+	 * along merrily.
 	 */
-	now = ticks;
-	for (i = 0; i < ic->ic_nchans; i++) {
-		struct ieee80211_channel *c = &ic->ic_channels[i];
-		if (c->ic_freq == chan->ic_freq) {
-			c->ic_state &= ~IEEE80211_CHANSTATE_CACDONE;
-			c->ic_state |= IEEE80211_CHANSTATE_RADAR;
-			dfs->nol_event[i] = now;
+	if (ieee80211_dfs_debug == DFS_DBG_NOCSANOL) {
+		announce_radar(ic->ic_ifp, chan, chan);
+		ieee80211_notify_radar(ic, chan);
+		return;
+	}
+
+	/*
+	 * Don't mark the channel and don't put it into NOL
+	 * if we're doing DFS debugging.
+	 */
+	if (ieee80211_dfs_debug == DFS_DBG_NONE) {
+		/*
+		 * Mark all entries with this frequency.  Notify user
+		 * space and arrange for notification when the radar
+		 * indication is cleared.  Then kick the NOL processing
+		 * thread if not already running.
+		 */
+		now = ticks;
+		for (i = 0; i < ic->ic_nchans; i++) {
+			struct ieee80211_channel *c = &ic->ic_channels[i];
+			if (c->ic_freq == chan->ic_freq) {
+				c->ic_state &= ~IEEE80211_CHANSTATE_CACDONE;
+				c->ic_state |= IEEE80211_CHANSTATE_RADAR;
+				dfs->nol_event[i] = now;
+			}
 		}
+		ieee80211_notify_radar(ic, chan);
+		chan->ic_state |= IEEE80211_CHANSTATE_NORADAR;
+		if (!callout_pending(&dfs->nol_timer))
+			callout_reset(&dfs->nol_timer, NOL_TIMEOUT,
+			    dfs_timeout, ic);
 	}
-	ieee80211_notify_radar(ic, chan);
-	chan->ic_state |= IEEE80211_CHANSTATE_NORADAR;
-	if (!callout_pending(&dfs->nol_timer))
-		callout_reset(&dfs->nol_timer, NOL_TIMEOUT, dfs_timeout, ic);
 
 	/*
 	 * If radar is detected on the bss channel while
@@ -310,7 +352,15 @@
 	 */
 	if (chan == ic->ic_bsschan) {
 		/* XXX need a way to defer to user app */
-		dfs->newchan = ieee80211_dfs_pickchannel(ic);
+
+		/*
+		 * Don't flip over to a new channel if
+		 * we are currently doing DFS debugging.
+		 */
+		if (ieee80211_dfs_debug == DFS_DBG_NONE)
+			dfs->newchan = ieee80211_dfs_pickchannel(ic);
+		else
+			dfs->newchan = chan;
 
 		announce_radar(ic->ic_ifp, chan, dfs->newchan);
 
diff -r 7f838fc4de58 -r c769fd33bdf3 head/sys/net80211/ieee80211_dfs.h
--- a/head/sys/net80211/ieee80211_dfs.h	Wed Feb 01 11:31:56 2012 +0200
+++ b/head/sys/net80211/ieee80211_dfs.h	Wed Feb 01 11:32:14 2012 +0200
@@ -22,7 +22,7 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- * $FreeBSD: head/sys/net80211/ieee80211_dfs.h 186107 2008-12-15 01:26:33Z sam $
+ * $FreeBSD: head/sys/net80211/ieee80211_dfs.h 230793 2012-01-31 00:03:49Z adrian $
  */
 #ifndef _NET80211_IEEE80211_DFS_H_
 #define _NET80211_IEEE80211_DFS_H_
@@ -31,6 +31,12 @@
  * 802.11h/DFS definitions.
  */
 
+typedef enum {
+	DFS_DBG_NONE		= 0,
+	DFS_DBG_NONOL		= 1,
+	DFS_DBG_NOCSANOL	= 2
+} dfs_debug_t;
+
 struct ieee80211_dfs_state {
 	int		nol_event[IEEE80211_CHAN_MAX];
 	struct callout	nol_timer;		/* NOL list processing */
diff -r 7f838fc4de58 -r c769fd33bdf3 head/sys/net80211/ieee80211_hwmp.c
--- a/head/sys/net80211/ieee80211_hwmp.c	Wed Feb 01 11:31:56 2012 +0200
+++ b/head/sys/net80211/ieee80211_hwmp.c	Wed Feb 01 11:32:14 2012 +0200
@@ -28,20 +28,20 @@
  */ 
 #include <sys/cdefs.h>
 #ifdef __FreeBSD__
-__FBSDID("$FreeBSD: head/sys/net80211/ieee80211_hwmp.c 227309 2011-11-07 15:43:11Z ed $");
+__FBSDID("$FreeBSD: head/sys/net80211/ieee80211_hwmp.c 230752 2012-01-29 19:35:40Z adrian $");
 #endif
 
 /*
  * IEEE 802.11s Hybrid Wireless Mesh Protocol, HWMP.
- * 
+ *
  * Based on March 2009, D3.0 802.11s draft spec.
  */
 #include "opt_inet.h"
 #include "opt_wlan.h"
 
 #include <sys/param.h>
-#include <sys/systm.h> 
-#include <sys/mbuf.h>   
+#include <sys/systm.h>
+#include <sys/mbuf.h>
 #include <sys/malloc.h>
 #include <sys/kernel.h>
 
@@ -139,9 +139,13 @@
 typedef uint32_t ieee80211_hwmp_seq;
 #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_EQ(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)
 
+/* 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.
  */
@@ -677,7 +681,9 @@
 	struct ieee80211_mesh_state *ms = vap->iv_mesh;
 	struct ieee80211_mesh_route *rt = NULL;
 	struct ieee80211_mesh_route *rtorig = NULL;
-	struct ieee80211_hwmp_route *hrorig;
+	struct ieee80211_mesh_route *rttarg = NULL;
+	struct ieee80211_hwmp_route *hrorig = NULL;
+	struct ieee80211_hwmp_route *hrtarg = NULL;
 	struct ieee80211_hwmp_state *hs = vap->iv_hwmp;
 	struct ieee80211_meshprep_ie prep;
 
@@ -692,46 +698,89 @@
 		return;
 
 	IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
-	    "received PREQ, source %s", ether_sprintf(preq->preq_origaddr));
+	    "received PREQ, source %6D", preq->preq_origaddr, ":");
 
 	/*
-	 * Acceptance criteria: if the PREQ is not for us and
-	 * forwarding is disabled, discard this PREQ.
+	 * Acceptance criteria: if the PREQ is not for us or not broadcast
+	 * AND forwarding is disabled, discard this PREQ.
+	 * XXX: need to check PROXY
 	 */
-	if (!IEEE80211_ADDR_EQ(vap->iv_myaddr, PREQ_TADDR(0)) &&
+	if ((!IEEE80211_ADDR_EQ(vap->iv_myaddr, PREQ_TADDR(0)) ||
+	    !IEEE80211_IS_MULTICAST(PREQ_TADDR(0))) &&
 	    !(ms->ms_flags & IEEE80211_MESHFLAGS_FWD)) {
 		IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_HWMP,
 		    preq->preq_origaddr, NULL, "%s", "not accepting PREQ");
 		return;
 	}
+	/*
+	 * Acceptance criteria: if unicast addressed 
+	 * AND no valid forwarding for Target of PREQ, discard this PREQ.
+	 */
+	rttarg = ieee80211_mesh_rt_find(vap, PREQ_TADDR(0));
+	if(rttarg != NULL)
+		hrtarg = IEEE80211_MESH_ROUTE_PRIV(rttarg,
+		    struct ieee80211_hwmp_route);
+	/* Address mode: ucast */
+	if((preq->preq_flags & IEEE80211_MESHPREQ_FLAGS_AM) == 0 &&
+	    rttarg == NULL &&
+	    !IEEE80211_ADDR_EQ(vap->iv_myaddr, PREQ_TADDR(0))) {
+		IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_HWMP,
+		    preq->preq_origaddr, NULL,
+		    "unicast addressed PREQ of unknown target %6D",
+		    PREQ_TADDR(0), ":");
+		return;
+	}
+
+	/* PREQ ACCEPTED */
+
 	rtorig = ieee80211_mesh_rt_find(vap, preq->preq_origaddr);
-	if (rtorig == NULL)
+	if (rtorig == NULL) {
 		rtorig = ieee80211_mesh_rt_add(vap, preq->preq_origaddr);
+		IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
+		    "adding originator %6D", preq->preq_origaddr, ":");
+	}
 	if (rtorig == NULL) {
 		/* XXX stat */
 		return;
 	}
 	hrorig = IEEE80211_MESH_ROUTE_PRIV(rtorig, struct ieee80211_hwmp_route);
-	/*
-	 * Sequence number validation.
+
+	/* Data creation and update of forwarding information
+	 * according to Table 11C-8 for originator mesh STA.
 	 */
-	if (HWMP_SEQ_LEQ(preq->preq_id, hrorig->hr_preqid) &&
-	    HWMP_SEQ_LEQ(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;
+		IEEE80211_ADDR_COPY(rtorig->rt_nexthop, wh->i_addr2);
+		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);
+		/* path to orig is valid now */
+		rtorig->rt_flags |= IEEE80211_MESHRT_FLAGS_VALID;
+	}else if(hrtarg != NULL &&
+		HWMP_SEQ_EQ(hrtarg->hr_seq, PREQ_TSEQ(0)) &&
+		(rtorig->rt_flags & IEEE80211_MESHRT_FLAGS_VALID) == 0) {
 		IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
-		    "discard PREQ from %s, old seq no %u <= %u",
-		    ether_sprintf(preq->preq_origaddr),
+		    "discard PREQ from %6D, old seq no %u <= %u",
+		    preq->preq_origaddr, ":",
 		    preq->preq_origseq, hrorig->hr_seq);
 		return;
 	}
-	hrorig->hr_preqid = preq->preq_id;
-	hrorig->hr_seq = preq->preq_origseq;
+
+	/*
+	 * Forwarding information for transmitter mesh STA
+	 * [OPTIONAL: if metric improved]
+	 */
 
 	/*
 	 * Check if the PREQ is addressed to us.
 	 */
 	if (IEEE80211_ADDR_EQ(vap->iv_myaddr, PREQ_TADDR(0))) {
 		IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
-		    "reply to %s", ether_sprintf(preq->preq_origaddr));
+		    "reply to %6D", preq->preq_origaddr, ":");
 		/*
 		 * Build and send a PREP frame.
 		 */
@@ -771,14 +820,14 @@
 			rt = ieee80211_mesh_rt_add(vap, rootmac);
 			if (rt == NULL) {
 				IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
-				    "unable to add root mesh path to %s",
-				    ether_sprintf(rootmac));
+				    "unable to add root mesh path to %6D",
+				    rootmac, ":");
 				vap->iv_stats.is_mesh_rtaddfailed++;
 				return;
 			}
 		}
 		IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
-		    "root mesh station @ %s", ether_sprintf(rootmac));
+		    "root mesh station @ %6D", rootmac, ":");
 
 		/*
 		 * Reply with a PREP if we don't have a path to the root
@@ -819,25 +868,28 @@
 			if (preq->preq_ttl > 1 &&
 			    preq->preq_hopcount < hs->hs_maxhops) {
 				IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
-				    "forward PREQ from %s",
-				    ether_sprintf(preq->preq_origaddr));
+				    "forward PREQ from %6D",
+				    preq->preq_origaddr, ":");
 				/*
 				 * Propagate the original PREQ.
+				 * PREQ is unicast now to rt->rt_nexthop
 				 */
+				ppreq.preq_flags &=
+				    ~IEEE80211_MESHPREQ_FLAGS_AM;
 				ppreq.preq_hopcount += 1;
 				ppreq.preq_ttl -= 1;
 				ppreq.preq_metric +=
 				    ms->ms_pmetric->mpm_metric(ni);
 				/*
-				 * Set TO and unset RF bits because we are going
-				 * to send a PREP next.
+				 * Set TO and unset RF bits because we are
+				 * going to send a PREP next.
 				 */
 				ppreq.preq_targets[0].target_flags |=
 				    IEEE80211_MESHPREQ_TFLAGS_TO;
 				ppreq.preq_targets[0].target_flags &=
 				    ~IEEE80211_MESHPREQ_TFLAGS_RF;
 				hwmp_send_preq(ni, vap->iv_myaddr,
-				    broadcastaddr, &ppreq);
+				    rt->rt_nexthop, &ppreq);
 			}
 			/*
 			 * Check if we can send an intermediate Path Reply,
@@ -847,8 +899,8 @@
 				struct ieee80211_meshprep_ie prep;
 
 				IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
-				    "intermediate reply for PREQ from %s",
-				    ether_sprintf(preq->preq_origaddr));
+				    "intermediate reply for PREQ from %6D",
+				    preq->preq_origaddr, ":");
 				prep.prep_flags = 0;
 				prep.prep_hopcount = rt->rt_nhops + 1;
 				prep.prep_ttl = ms->ms_ttl;
@@ -873,9 +925,10 @@
 			if (rt == NULL) {
 				rt = ieee80211_mesh_rt_add(vap, PREQ_TADDR(0));
 				if (rt == NULL) {
-					IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP,
-					    ni, "unable to add PREQ path to %s",
-					    ether_sprintf(PREQ_TADDR(0)));
+					IEEE80211_NOTE(vap,
+					    IEEE80211_MSG_HWMP, ni,
+					    "unable to add PREQ path to %6D",
+					    PREQ_TADDR(0), ":");
 					vap->iv_stats.is_mesh_rtaddfailed++;
 					return;
 				}
@@ -888,8 +941,8 @@
 			hrorig->hr_preqid = preq->preq_id;
 
 			IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
-			    "forward PREQ from %s",
-			    ether_sprintf(preq->preq_origaddr));
+			    "forward PREQ from %6D",
+			    preq->preq_origaddr, ":");
 			ppreq.preq_hopcount += 1;
 			ppreq.preq_ttl -= 1;
 			ppreq.preq_metric += ms->ms_pmetric->mpm_metric(ni);
@@ -897,7 +950,6 @@
 			    &ppreq);
 		}
 	}
-
 }
 #undef	PREQ_TFLAGS
 #undef	PREQ_TADDR
@@ -921,7 +973,7 @@
 	/*
 	 * mesh preq action frame format
 	 *     [6] da
-	 *     [6] sa 
+	 *     [6] sa
 	 *     [6] addr3 = sa
 	 *     [1] action
 	 *     [1] category
@@ -943,6 +995,7 @@
 	struct ieee80211com *ic = vap->iv_ic;
 	struct ifnet *ifp = vap->iv_ifp;
 	struct mbuf *m, *next;
+	uint32_t metric = 0;
 
 	/*
 	 * Acceptance criteria: if the corresponding PREQ was not generated
@@ -956,19 +1009,21 @@
 		return;
 
 	IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
-	    "received PREP from %s", ether_sprintf(prep->prep_targetaddr));
+	    "received PREP from %6D", prep->prep_targetaddr, ":");
 
 	rt = ieee80211_mesh_rt_find(vap, prep->prep_targetaddr);
 	if (rt == NULL) {
 		/*
 		 * If we have no entry this could be a reply to a root PREQ.
+		 * XXX: not true anymore cause we dont create entry for target
+		 *  when propagating PREQs like the old code did.
 		 */
 		if (hs->hs_rootmode != IEEE80211_HWMP_ROOTMODE_DISABLED) {
 			rt = ieee80211_mesh_rt_add(vap, prep->prep_targetaddr);
 			if (rt == NULL) {
 				IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP,
-				    ni, "unable to add PREP path to %s",
-				    ether_sprintf(prep->prep_targetaddr));
+				    ni, "unable to add PREP path to %6D",
+				    prep->prep_targetaddr, ":");
 				vap->iv_stats.is_mesh_rtaddfailed++;
 				return;
 			}
@@ -978,24 +1033,34 @@
 			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_targetaddr),
+			    "add root path to %6D nhops %d metric %lu (PREP)",
+			    prep->prep_targetaddr, ":",
 			    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_targetseq, hr->hr_seq)) {
-		IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
-		    "discard PREP from %s, old seq no %u <= %u",
-		    ether_sprintf(prep->prep_targetaddr),
-		    prep->prep_targetseq, hr->hr_seq);
-		return;
+	if ((rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID)) {
+		if (HWMP_SEQ_LT(prep->prep_targetseq, hr->hr_seq)) {
+			IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
+			    "discard PREP from %6D, old seq no %u < %u",
+			    prep->prep_targetaddr, ":",
+			    prep->prep_targetseq, hr->hr_seq);
+			return;
+		} else if (HWMP_SEQ_LEQ(prep->prep_targetseq, hr->hr_seq) &&
+		    prep->prep_metric > rt->rt_metric) {
+			IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
+			    "discard PREP from %6D, new metric %u > %u",
+			    prep->prep_targetaddr, ":",
+			    prep->prep_metric, rt->rt_metric);
+			return;
+		}
 	}
+
 	hr->hr_seq = prep->prep_targetseq;
 	/*
 	 * If it's NOT for us, propagate the PREP.
@@ -1003,26 +1068,26 @@
 	if (!IEEE80211_ADDR_EQ(vap->iv_myaddr, prep->prep_origaddr) &&
 	    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_targetaddr));
+		    "propagate PREP from %6D",
+		    prep->prep_targetaddr, ":");
 
 		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_targetaddr, vap->iv_myaddr);
 		hwmp_send_prep(ni, vap->iv_myaddr, broadcastaddr, &pprep);
 	}
 	hr = IEEE80211_MESH_ROUTE_PRIV(rt, struct ieee80211_hwmp_route);
 	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_targetaddr));
+		    "discard PREP for %6D, route is marked PROXY",
+		    prep->prep_targetaddr, ":");
 		vap->iv_stats.is_hwmp_proxy++;
-	} else if (prep->prep_origseq == hr->hr_origseq) {
+	/* NB: first path discovery always fails */
+	} else if (hr->hr_origseq == 0 ||
+	    prep->prep_origseq == hr->hr_origseq) {
 		/*
 		 * Check if we already have a path to this node.
 		 * If we do, check if this path reply contains a
@@ -1031,32 +1096,35 @@
 		if ((rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID) == 0 ||
 		    (prep->prep_hopcount < rt->rt_nhops ||
 		     prep->prep_metric < rt->rt_metric)) {
+			hr->hr_origseq = prep->prep_origseq;
+			metric = prep->prep_metric +
+			    ms->ms_pmetric->mpm_metric(ni);
 			IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
-			    "%s path to %s, hopcount %d:%d metric %d:%d",
+			    "%s path to %6D, hopcount %d:%d metric %d:%d",
 			    rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID ?
 				"prefer" : "update",
-			    ether_sprintf(prep->prep_origaddr),
+			    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_nhops = prep->prep_hopcount + 1;
 			rt->rt_lifetime = prep->prep_lifetime;
-			rt->rt_metric = prep->prep_metric;
+			rt->rt_metric = 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_targetaddr),
+			    "ignore PREP for %6D, hopcount %d:%d metric %d:%d",
+			    prep->prep_targetaddr, ":",
 			    rt->rt_nhops, prep->prep_hopcount,
 			    rt->rt_metric, prep->prep_metric);
 		}
 	} else {
 		IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
-		    "discard PREP for %s, wrong seqno %u != %u",
-		    ether_sprintf(prep->prep_targetaddr), prep->prep_origseq,
-		    hr->hr_seq);
+		    "discard PREP for %6D, wrong orig seqno %u != %u",
+		    prep->prep_targetaddr, ":", prep->prep_origseq,
+		    hr->hr_origseq);
 		vap->iv_stats.is_hwmp_wrongseq++;
-	} 
+	}
 	/*
 	 * Check for frames queued awaiting path discovery.
 	 * XXX probably can tell exactly and avoid remove call
@@ -1064,9 +1132,9 @@
 	 *     stuck back on the stageq because there won't be
 	 *     a path.
 	 */
-	m = ieee80211_ageq_remove(&ic->ic_stageq, 
+	m = ieee80211_ageq_remove(&ic->ic_stageq,
 	    (struct ieee80211_node *)(uintptr_t)
-		ieee80211_mac_hash(ic, rt->rt_dest));
+	    ieee80211_mac_hash(ic, rt->rt_dest));
 	for (; m != NULL; m = next) {
 		next = m->m_nextpkt;
 		m->m_nextpkt = NULL;
@@ -1087,7 +1155,7 @@
 	/*
 	 * mesh prep action frame format
 	 *     [6] da
-	 *     [6] sa 
+	 *     [6] sa
 	 *     [6] addr3 = sa
 	 *     [1] action
 	 *     [1] category
@@ -1146,7 +1214,7 @@
 	struct ieee80211_mesh_state *ms = vap->iv_mesh;
 	struct ieee80211_mesh_route *rt = NULL;
 	struct ieee80211_hwmp_route *hr;
- 	struct ieee80211_meshperr_ie pperr;
+	struct ieee80211_meshperr_ie pperr;
 	int i, forward = 0;
 
 	/*
@@ -1165,7 +1233,7 @@
 		if (rt == NULL)
 			continue;
 		hr = IEEE80211_MESH_ROUTE_PRIV(rt, struct ieee80211_hwmp_route);
-		if (!(PERR_DFLAGS(0) & IEEE80211_MESHPERR_DFLAGS_USN) && 
+		if (!(PERR_DFLAGS(0) & IEEE80211_MESHPERR_DFLAGS_USN) &&
 		    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);
@@ -1179,7 +1247,7 @@
 	 */
 	if (forward && perr->perr_ttl > 1) {
 		IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
-		    "propagate PERR from %s", ether_sprintf(wh->i_addr2));
+		    "propagate PERR from %6D", wh->i_addr2, ":");
 		memcpy(&pperr, perr, sizeof(*perr));
 		pperr.perr_ttl--;
 		hwmp_send_perr(vap->iv_bss, vap->iv_myaddr, broadcastaddr,
@@ -1267,7 +1335,7 @@
 	/*
 	 * mesh rann action frame format
 	 *     [6] da
-	 *     [6] sa 
+	 *     [6] sa
 	 *     [6] addr3 = sa
 	 *     [1] action
 	 *     [1] category
@@ -1306,8 +1374,8 @@
 			rt = ieee80211_mesh_rt_add(vap, dest);
 			if (rt == NULL) {
 				IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP,
-				    ni, "unable to add discovery path to %s",
-				    ether_sprintf(dest));
+				    ni, "unable to add discovery path to %6D",
+				    dest, ":");
 				vap->iv_stats.is_mesh_rtaddfailed++;
 				goto done;
 			}
@@ -1323,13 +1391,15 @@
 			/* XXX check preq retries */
 			sendpreq = 1;
 			IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_HWMP, dest,
-			    "start path discovery (src %s)",
+			    "start path discovery (src %s), target seq %u",
 			    m == NULL ? "<none>" : ether_sprintf(
-				mtod(m, struct ether_header *)->ether_shost));
+			    mtod(m, struct ether_header *)->ether_shost),
+			    hr->hr_seq);
 			/*
 			 * Try to discover the path for this node.
+			 * Group addressed PREQ Case A
 			 */
-			preq.preq_flags = 0;
+			preq.preq_flags = IEEE80211_MESHPREQ_FLAGS_AM;
 			preq.preq_hopcount = 0;
 			preq.preq_ttl = ms->ms_ttl;
 			preq.preq_id = ++hs->hs_preqid;
@@ -1345,7 +1415,7 @@
 			if (ieee80211_hwmp_replyforward)
 				PREQ_TFLAGS(0) |= IEEE80211_MESHPREQ_TFLAGS_RF;
 			PREQ_TFLAGS(0) |= IEEE80211_MESHPREQ_TFLAGS_USN;
-			PREQ_TSEQ(0) = 0;
+			PREQ_TSEQ(0) = hr->hr_seq;
 			/* XXX check return value */
 			hwmp_send_preq(vap->iv_bss, vap->iv_myaddr,
 			    broadcastaddr, &preq);
@@ -1391,7 +1461,7 @@
 {
 	struct ieee80211_hwmp_state *hs = vap->iv_hwmp;
 	int error;
- 
+
 	if (vap->iv_opmode != IEEE80211_M_MBSS)
 		return ENOSYS;
 	error = 0;


More information about the Zrouter-src-freebsd mailing list