svn commit: r195284 - projects/mesh11s/sys/net80211

Rui Paulo rpaulo at FreeBSD.org
Thu Jul 2 12:41:22 UTC 2009


Author: rpaulo
Date: Thu Jul  2 12:41:21 2009
New Revision: 195284
URL: http://svn.freebsd.org/changeset/base/195284

Log:
  Finish proactive root mode implementation.
  
  Sponsored by:	The FreeBSD Foundation

Modified:
  projects/mesh11s/sys/net80211/ieee80211_hwmp.c
  projects/mesh11s/sys/net80211/ieee80211_hwmp.h
  projects/mesh11s/sys/net80211/ieee80211_ioctl.h

Modified: projects/mesh11s/sys/net80211/ieee80211_hwmp.c
==============================================================================
--- projects/mesh11s/sys/net80211/ieee80211_hwmp.c	Thu Jul  2 10:02:10 2009	(r195283)
+++ projects/mesh11s/sys/net80211/ieee80211_hwmp.c	Thu Jul  2 12:41:21 2009	(r195284)
@@ -83,6 +83,8 @@ static uint8_t *hwmp_add_meshperr(uint8_
     const struct ieee80211_meshperr_ie *);
 static uint8_t *hwmp_add_meshrann(uint8_t *,
     const struct ieee80211_meshrann_ie *);
+static void	hwmp_rootmode_setup(struct ieee80211vap *);
+static void	hwmp_rootmode_cb(void *);
 static void	hwmp_recv_preq(struct ieee80211vap *, struct ieee80211_node *,
     const struct ieee80211_frame *, const struct ieee80211_meshpreq_ie *);
 static int	hwmp_send_preq(struct ieee80211_node *,
@@ -121,6 +123,9 @@ static const struct timeval ieee80211_hw
 
 #define	timeval2msecs(tv)	(tv.tv_sec * 1000 + tv.tv_usec / 1000)
 
+#define	HWMP_ROOTMODEINT msecs_to_ticks(timeval2msecs(ieee80211_hmwp_rootint))
+#define	HWMP_RANNMODEINT msecs_to_ticks(timeval2msecs(ieee80211_hmwp_rannint))
+
 #define	HWMP_LOCK(hs)		mtx_lock(&(hs)->hs_lock)
 #define	HWMP_UNLOCK(hs)		mtx_unlock(&(hs)->hs_lock)
 
@@ -170,6 +175,10 @@ hwmp_rt_add(struct ieee80211vap *vap, co
 
 	KASSERT(hwmp_rt_find(vap, dest) == NULL,
 	    ("%s: duplicate entry in the routing table", __func__));
+	KASSERT(!IEEE80211_ADDR_EQ(vap->iv_myaddr, dest),
+	    ("%s: adding self to the routing table", __func__));
+	KASSERT(!IEEE80211_ADDR_EQ(broadcastaddr, dest),
+	    ("%s: adding broadcast to the routing table", __func__));
 
 	rt = malloc(sizeof(struct ieee80211_hwmp_route), M_80211_HWMP,
 	    M_NOWAIT | M_ZERO);
@@ -233,6 +242,7 @@ ieee80211_hwmp_vattach(struct ieee80211v
 	mtx_init(&hs->hs_lock, "HWMP", "802.11s HWMP", MTX_DEF);
 	hs->hs_maxhops = IEEE80211_HWMP_DEFAULT_MAXHOPS;
 	hs->hs_ttl = IEEE80211_HWMP_DEFAULT_TTL;
+	callout_init(&hs->hs_roottimer, CALLOUT_MPSAFE);                                        
 	vap->iv_hwmp = hs;
 }
 
@@ -242,6 +252,8 @@ ieee80211_hwmp_vdetach(struct ieee80211v
 	struct ieee80211_hwmp_state *hs = vap->iv_hwmp;
 
 	hwmp_rt_flush(vap);
+	if (callout_pending(&hs->hs_roottimer))
+		callout_stop(&hs->hs_roottimer);
 	mtx_destroy(&hs->hs_lock);
 	free(vap->iv_hwmp, M_80211_HWMP);
 } 
@@ -250,10 +262,14 @@ int
 ieee80211_hwmp_newstate(struct ieee80211vap *vap, enum ieee80211_state ostate, int arg)
 {
 	enum ieee80211_state nstate = vap->iv_state;
+	struct ieee80211_hwmp_state *hs = vap->iv_hwmp;
 
 	/* Flush the table on INIT -> SCAN, e.g. interface down & up */
-	if (nstate == IEEE80211_S_SCAN && ostate == IEEE80211_S_INIT)
+	if (nstate == IEEE80211_S_SCAN && ostate == IEEE80211_S_INIT) {
 		hwmp_rt_flush(vap);
+		if (callout_pending(&hs->hs_roottimer))
+			callout_stop(&hs->hs_roottimer);
+	}
 	return 0;
 }
 
@@ -553,7 +569,18 @@ hwmp_add_meshrann(uint8_t *frm, const st
 	return frm;
 }
 
-#ifdef notyet
+static void
+hwmp_rootmode_setup(struct ieee80211vap *vap)
+{
+	struct ieee80211_hwmp_state *hs = vap->iv_hwmp;
+
+	if (hs->hs_rootmode != IEEE80211_HWMP_ROOTMODE_DISABLED)
+		callout_reset(&hs->hs_roottimer, HWMP_ROOTMODEINT,
+		    hwmp_rootmode_cb, vap);
+	else
+		callout_stop(&hs->hs_roottimer);
+}
+
 /*
  * Send a broadcast Path Request to find all nodes on the mesh. We are
  * called when the vap is configured as a HWMP root node.
@@ -562,14 +589,17 @@ hwmp_add_meshrann(uint8_t *frm, const st
 #define	PREQ_TADDR(n)	preq.preq_targets[n].target_addr
 #define	PREQ_TSEQ(n)	preq.preq_targets[n].target_seq
 static void
-hwmp_rootmode_cb(struct ieee80211vap *vap)
+hwmp_rootmode_cb(void *arg)
 {
+	struct ieee80211vap *vap = (struct ieee80211vap *)arg;
 	struct ieee80211_hwmp_state *hs = vap->iv_hwmp;
 	struct ieee80211_meshpreq_ie preq;
 
+	IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, vap->iv_bss,
+	    "%s", "sending broadcast PREQ");
+
 	/* XXX check portal role */
-	preq.preq_flags = 0;
-	preq.preq_flags |= IEEE80211_MESHPREQ_FLAGS_AM;
+	preq.preq_flags = IEEE80211_MESHPREQ_FLAGS_AM;
 	if (hs->hs_rootmode == IEEE80211_HWMP_ROOTMODE_PROACTIVE)
 		preq.preq_flags |= IEEE80211_MESHPREQ_FLAGS_PP;
 	preq.preq_hopcount = 0;
@@ -584,12 +614,13 @@ hwmp_rootmode_cb(struct ieee80211vap *va
 	PREQ_TFLAGS(0) = IEEE80211_MESHPREQ_TFLAGS_TO |
 	    IEEE80211_MESHPREQ_TFLAGS_RF;
 	PREQ_TSEQ(0) = 0;
+	vap->iv_stats.is_hwmp_rootreqs++;
 	hwmp_send_preq(vap->iv_bss, vap->iv_myaddr, broadcastaddr, &preq);
+	hwmp_rootmode_setup(vap);
 }
 #undef	PREQ_TFLAGS
 #undef	PREQ_TADDR
 #undef	PREQ_TSEQ
-#endif
 
 #define	PREQ_TFLAGS(n)	preq->preq_targets[n].target_flags
 #define	PREQ_TADDR(n)	preq->preq_targets[n].target_addr
@@ -657,6 +688,47 @@ hwmp_recv_preq(struct ieee80211vap *vap,
 			ieee80211_hwmp_discover(vap, rt->rt_dest, NULL);
 		return;
 	}
+	/*
+	 * Proactive PREQ: reply with a proactive PREP to the
+	 * root STA if requested.
+	 */
+	if (IEEE80211_ADDR_EQ(PREQ_TADDR(0), broadcastaddr) &&
+	    (PREQ_TFLAGS(0) &
+	    ((IEEE80211_MESHPREQ_TFLAGS_TO|IEEE80211_MESHPREQ_TFLAGS_RF) ==
+	    (IEEE80211_MESHPREQ_TFLAGS_TO|IEEE80211_MESHPREQ_TFLAGS_RF)))) {
+		uint8_t rootmac[IEEE80211_ADDR_LEN];
+
+		IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
+		    "root mesh station @ %s",
+		    ether_sprintf(preq->preq_origaddr));
+		IEEE80211_ADDR_COPY(rootmac, preq->preq_origaddr);
+		rt = hwmp_rt_find(vap, rootmac);
+		if (rt == NULL)
+			rt = hwmp_rt_add(vap, rootmac);
+		/*
+		 * Reply with a PREP if we don't have a path to the root
+		 * or if the root sent us a proactive PREQ.
+		 */
+		if (IEEE80211_ADDR_EQ(rt->rt_nexthop, invalidaddr) ||
+		    (preq->preq_flags & IEEE80211_MESHPREQ_FLAGS_PP)) {
+			prep.prep_flags = 0;
+			prep.prep_hopcount = 0;
+			prep.prep_ttl = hs->hs_ttl;
+			IEEE80211_ADDR_COPY(prep.prep_origaddr,
+			    vap->iv_myaddr);
+			prep.prep_origseq = preq->preq_origseq;
+			prep.prep_targetseq = ++hs->hs_seq;
+			prep.prep_lifetime = preq->preq_lifetime;
+			prep.prep_metric = IEEE80211_MESHLMETRIC_INITIALVAL;
+			IEEE80211_ADDR_COPY(prep.prep_targetaddr,
+			    rootmac);
+			prep.prep_targetseq = PREQ_TSEQ(0);
+			hwmp_send_prep(vap->iv_bss, vap->iv_myaddr,
+			    broadcastaddr, &prep);
+		}
+		ieee80211_hwmp_discover(vap, rootmac, NULL);
+		return;
+	}
 	rt = hwmp_rt_find(vap, PREQ_TADDR(0));
 
 	/* XXX missing. Check for AE bit and update proxy information */
@@ -745,38 +817,6 @@ hwmp_recv_preq(struct ieee80211vap *vap,
 		}
 	}
 
-	/*
-	 * Proactive PREQ: reply with a proactive PREP to the
-	 * root STA if requested.
-	 */
-	if (IEEE80211_ADDR_EQ(PREQ_TADDR(0), broadcastaddr) &&
-	    (PREQ_TFLAGS(0) &
-	    ((IEEE80211_MESHPREQ_TFLAGS_TO|IEEE80211_MESHPREQ_TFLAGS_RF) ==
-	    (IEEE80211_MESHPREQ_TFLAGS_TO|IEEE80211_MESHPREQ_TFLAGS_RF)))) {
-		rt = hwmp_rt_find(vap, preq->preq_origaddr);
-		if (rt == NULL)
-			rt = hwmp_rt_add(vap, preq->preq_origaddr);
-		/*
-		 * Reply with a PREP if we don't have a path to the root
-		 * or if the root sent us a proactive PREQ.
-		 */
-		if (IEEE80211_ADDR_EQ(rt->rt_nexthop, invalidaddr) ||
-		    (preq->preq_flags & IEEE80211_MESHPREQ_FLAGS_PP)) {
-			prep.prep_flags = 0;
-			prep.prep_hopcount = 0;
-			prep.prep_ttl = hs->hs_ttl;
-			IEEE80211_ADDR_COPY(prep.prep_targetaddr,
-			    vap->iv_myaddr);
-			prep.prep_targetseq = ++hs->hs_seq;
-			prep.prep_lifetime = preq->preq_lifetime;
-			prep.prep_metric = IEEE80211_MESHLMETRIC_INITIALVAL;
-			IEEE80211_ADDR_COPY(prep.prep_origaddr,
-			    preq->preq_origaddr);
-			prep.prep_origseq = preq->preq_origseq;
-			hwmp_send_prep(vap->iv_bss, vap->iv_myaddr,
-			    broadcastaddr, &prep);
-		}
-	}
 }
 #undef	PREQ_TFLAGS
 #undef	PREQ_TADDR
@@ -816,14 +856,15 @@ hwmp_recv_prep(struct ieee80211vap *vap,
     const struct ieee80211_frame *wh, const struct ieee80211_meshprep_ie *prep)
 {
 	struct ieee80211_mesh_state *ms = vap->iv_mesh;
+	struct ieee80211_hwmp_state *hs = vap->iv_hwmp;
 	struct ieee80211_hwmp_route *rt = NULL;
 	struct ieee80211com *ic = vap->iv_ic;
 	struct ifnet *ifp = vap->iv_ifp;
 	struct mbuf *m, *next;
 
 	/*
-	 * Acceptance criteria: if the PREP was not generated by us and
-	 * forwarding is disabled, discard this PREP.
+	 * Acceptance criteria: if the corresponding PREQ was not generated
+	 * by us and forwarding is disabled, discard this PREP.
 	 */
 	if (!IEEE80211_ADDR_EQ(vap->iv_myaddr, prep->prep_origaddr) &&
 	    !(ms->ms_flags & IEEE80211_MESHFLAGS_FWD))
@@ -853,8 +894,21 @@ hwmp_recv_prep(struct ieee80211vap *vap,
 	}
 
 	rt = hwmp_rt_find(vap, prep->prep_origaddr);
-	if (rt == NULL)
+	if (rt == NULL) {
+		/*
+		 * If we have no entry this could be a reply to a root PREQ.
+		 */
+		if (hs->hs_rootmode != IEEE80211_HWMP_ROOTMODE_DISABLED) {
+			printf("1\n");
+			rt = hwmp_rt_add(vap, prep->prep_origaddr);
+			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;
+			return;
+		} 
 		return;
+	}
 	if (prep->prep_targetseq == rt->rt_seq) {
 		int useprep = 0;
 		/*
@@ -1124,7 +1178,7 @@ ieee80211_hwmp_discover(struct ieee80211
 	    ("not a mesh vap, opmode %d", vap->iv_opmode));
 
 	KASSERT(!IEEE80211_ADDR_EQ(vap->iv_myaddr, dest),
-	    ("discovering self!"));
+	    ("%s: discovering self!", __func__));
 
 	ni = NULL;
 	if (!IEEE80211_IS_MULTICAST(dest)) {
@@ -1339,6 +1393,7 @@ hwmp_ioctl_set80211(struct ieee80211vap 
 		if (ireq->i_val < 0 || ireq->i_val > 3)
 			return EINVAL;
 		hs->hs_rootmode = ireq->i_val;
+		hwmp_rootmode_setup(vap);
 		break;
 	case IEEE80211_IOC_HWMP_MAXHOPS:
 		if (ireq->i_val <= 0 || ireq->i_val > 255)

Modified: projects/mesh11s/sys/net80211/ieee80211_hwmp.h
==============================================================================
--- projects/mesh11s/sys/net80211/ieee80211_hwmp.h	Thu Jul  2 10:02:10 2009	(r195283)
+++ projects/mesh11s/sys/net80211/ieee80211_hwmp.h	Thu Jul  2 12:41:21 2009	(r195284)
@@ -64,6 +64,7 @@ struct ieee80211_hwmp_state {
 	struct timeval		hs_lastperr;	/* last time we sent a PERR */
 	struct mtx		hs_lock;	/* lock for the fi table */
 	int			hs_rootmode;	/* proactive HWMP */
+	struct callout		hs_roottimer;
 	uint8_t			hs_maxhops;	/* max hop count */
 	uint8_t			hs_ttl;		/* HWMP ttl */
 };

Modified: projects/mesh11s/sys/net80211/ieee80211_ioctl.h
==============================================================================
--- projects/mesh11s/sys/net80211/ieee80211_ioctl.h	Thu Jul  2 10:02:10 2009	(r195283)
+++ projects/mesh11s/sys/net80211/ieee80211_ioctl.h	Thu Jul  2 12:41:21 2009	(r195284)
@@ -233,6 +233,7 @@ struct ieee80211_stats {
 	uint32_t	is_mesh_fwd_nopath;	/* mesh not fwd'd 'cuz path unknown */
 
 	uint32_t	is_hwmp_wrongseq;	/* wrong hwmp seq no. */
+	uint32_t	is_hwmp_rootreqs;	/* root PREQs sent */
 
 	uint32_t	is_spare[8];
 };


More information about the svn-src-projects mailing list