svn commit: r195158 - in projects/mesh11s: sbin/ifconfig sys/net80211

Rui Paulo rpaulo at FreeBSD.org
Mon Jun 29 15:53:53 UTC 2009


Author: rpaulo
Date: Mon Jun 29 15:53:52 2009
New Revision: 195158
URL: http://svn.freebsd.org/changeset/base/195158

Log:
  * introduce the HWMP TTL and stop using the mesh TTL in HWMP
  * misc HWMP fixups, now we display the correct hop count and metric
  * disable age while the panic isn't fixed
  * handle PERR by removing the entry from the HWMP table and propating
  the PERR
  * add a new callback function to be called whenever a peer link goes
  down
  * add ifconfig wlan0 hwmpttl setting
  
  Sponsored by:	The FreeBSD Foundation

Modified:
  projects/mesh11s/sbin/ifconfig/ifieee80211.c
  projects/mesh11s/sys/net80211/ieee80211_hwmp.c
  projects/mesh11s/sys/net80211/ieee80211_hwmp.h
  projects/mesh11s/sys/net80211/ieee80211_ioctl.h
  projects/mesh11s/sys/net80211/ieee80211_mesh.c

Modified: projects/mesh11s/sbin/ifconfig/ifieee80211.c
==============================================================================
--- projects/mesh11s/sbin/ifconfig/ifieee80211.c	Mon Jun 29 15:23:50 2009	(r195157)
+++ projects/mesh11s/sbin/ifconfig/ifieee80211.c	Mon Jun 29 15:53:52 2009	(r195158)
@@ -1329,6 +1329,12 @@ DECL_CMD_FUNC(set80211hwmpmaxhops, val, 
 	set80211(s, IEEE80211_IOC_HWMP_MAXHOPS, atoi(val), 0, NULL);
 }
 
+static
+DECL_CMD_FUNC(set80211hwmpttl, val, d)
+{
+	set80211(s, IEEE80211_IOC_HWMP_TTL, atoi(val), 0, NULL);
+}
+
 static void
 set80211pureg(const char *val, int d, int s, const struct afswtch *rafp)
 {
@@ -4823,6 +4829,9 @@ end:
 		if (get80211val(s, IEEE80211_IOC_HWMP_MAXHOPS, &val) != -1) {
 			LINE_CHECK("hwmpmaxhops %u", val);
 		}
+		if (get80211val(s, IEEE80211_IOC_HWMP_TTL, &val) != -1) {
+			LINE_CHECK("hwmpttl %u", val);
+		}
 	}
 
 	LINE_BREAK();
@@ -5136,9 +5145,6 @@ static struct cmd ieee80211_cmds[] = {
 	DEF_CMD_ARG("mac:add",		set80211addmac),
 	DEF_CMD_ARG("mac:del",		set80211delmac),
 	DEF_CMD_ARG("mac:kick",		set80211kickmac),
-	DEF_CMD("hwmp:flush",	IEEE80211_HWMP_CMD_FLUSH,	set80211hwmpcmd),
-	DEF_CMD_ARG("hwmp:add",		set80211addhwmp),
-	DEF_CMD_ARG("hwmp:del",		set80211delhwmp),
 	DEF_CMD("pureg",	1,	set80211pureg),
 	DEF_CMD("-pureg",	0,	set80211pureg),
 	DEF_CMD("ff",		1,	set80211fastframes),
@@ -5229,8 +5235,12 @@ static struct cmd ieee80211_cmds[] = {
 	DEF_CMD("-meshforward",	0,	set80211meshforward),
 	DEF_CMD("meshpeering",	1,	set80211meshpeering),
 	DEF_CMD("-meshpeering",	0,	set80211meshpeering),
+	DEF_CMD("hwmp:flush",	IEEE80211_HWMP_CMD_FLUSH,	set80211hwmpcmd),
+	DEF_CMD_ARG("hwmp:add",		set80211addhwmp),
+	DEF_CMD_ARG("hwmp:del",		set80211delhwmp),
 	DEF_CMD_ARG("hwmprootmode",	set80211hwmprootmode),
 	DEF_CMD_ARG("hwmpmaxhops",	set80211hwmpmaxhops),
+	DEF_CMD_ARG("hwmptll",		set80211hwmpttl),
 
 	/* vap cloning support */
 	DEF_CLONE_CMD_ARG("wlanaddr",	set80211clone_wlanaddr),

Modified: projects/mesh11s/sys/net80211/ieee80211_hwmp.c
==============================================================================
--- projects/mesh11s/sys/net80211/ieee80211_hwmp.c	Mon Jun 29 15:23:50 2009	(r195157)
+++ projects/mesh11s/sys/net80211/ieee80211_hwmp.c	Mon Jun 29 15:53:52 2009	(r195158)
@@ -140,6 +140,7 @@ SYSCTL_INT(_net_wlan_hwmp, OID_AUTO, rep
 MALLOC_DEFINE(M_80211_HWMP, "80211hwmp", "802.11 HWMP routing table");
 
 #define	IEEE80211_HWMP_DEFAULT_MAXHOPS	31
+#define	IEEE80211_HWMP_DEFAULT_TTL	31
 
 /*
  * Helper functions to manipulate the HWMP routing table.
@@ -232,6 +233,7 @@ ieee80211_hwmp_vattach(struct ieee80211v
 	TAILQ_INIT(&hs->hs_head);
 	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;
 	vap->iv_hwmp = hs;
 }
 
@@ -583,9 +585,6 @@ hwmp_recv_preq(struct ieee80211vap *vap,
 		    preq->preq_origaddr, NULL, "%s", "not accepting PREQ");
 		return;
 	}
-	fi = hwmp_rt_find(vap, PREQ_TADDR(0));
-	if (fi)
-		fi->fi_preqid = preq->preq_id;
 	/*
 	 * Check if the PREQ is addressed to us.
 	 * XXX: check if this is part of a proxy address.
@@ -600,7 +599,7 @@ hwmp_recv_preq(struct ieee80211vap *vap,
 		 */
 		prep.prep_flags = 0;
 		prep.prep_hopcount = 0;
-		prep.prep_ttl = ms->ms_ttl;
+		prep.prep_ttl = hs->hs_ttl;
 		IEEE80211_ADDR_COPY(prep.prep_targetaddr, preq->preq_origaddr);
 		prep.prep_targetseq = preq->preq_origseq;
 		prep.prep_lifetime = preq->preq_lifetime;
@@ -608,24 +607,28 @@ hwmp_recv_preq(struct ieee80211vap *vap,
 		IEEE80211_ADDR_COPY(prep.prep_origaddr, vap->iv_myaddr);
 		prep.prep_origseq = hs->hs_seq++;
 		hwmp_send_prep(ni, vap->iv_myaddr, wh->i_addr2, &prep);
+#if 0
 		/*
 		 * Build the reverse path, if we don't have it already.
 		 */
 		fi = hwmp_rt_find(vap, preq->preq_origaddr);
 		if (fi == NULL) {
-			fi = hwmp_rt_add(vap, preq->preq_origaddr);
-			ieee80211_hwmp_discover(vap, fi->fi_dest, NULL);
+			uint8_t *dest = (uint8_t *)preq->preq_origaddr;
+
+			ieee80211_hwmp_discover(vap, dest, NULL);
 		} else if (IEEE80211_ADDR_EQ(fi->fi_nexthop, invalidaddr))
 			ieee80211_hwmp_discover(vap, fi->fi_dest, NULL);
+#endif
 		return;
 	}
+	fi = hwmp_rt_find(vap, PREQ_TADDR(0));
 
 	/* XXX missing. Check for AE bit and update proxy information */
 
 	/*
-	 * Intermediate reply for PREQs with 1 target.
+	 * Forwarding and Intermediate reply for PREQs with 1 target.
 	 */
-	if (preq->preq_ttl > 1 && preq->preq_tcount == 1) {
+	if (preq->preq_tcount == 1) {
 		struct ieee80211_meshpreq_ie ppreq; /* propagated PREQ */
 
 		memcpy(&ppreq, preq, sizeof(ppreq));
@@ -634,27 +637,33 @@ hwmp_recv_preq(struct ieee80211vap *vap,
 		 */
 		if (fi != NULL &&
 		    !IEEE80211_ADDR_EQ(fi->fi_nexthop, invalidaddr)) {
-			IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
-			    "forwarding PREQ from %s",
-			    ether_sprintf(preq->preq_origaddr));
-			/*
-			 * Propagate the original PREQ.
-			 */
-			ppreq.preq_hopcount += 1;
-			ppreq.preq_ttl -= 1;
-			ppreq.preq_metric += ieee80211_airtime_calc(ni);
-			/*
-			 * 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);
+			fi->fi_preqid = preq->preq_id;
+			fi->fi_seq = preq->preq_origseq;
+			if (preq->preq_ttl > 1) {
+
+				IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
+				    "forwarding PREQ from %s",
+				    ether_sprintf(preq->preq_origaddr));
+				/*
+				 * Propagate the original PREQ.
+				 */
+				ppreq.preq_hopcount += 1;
+				ppreq.preq_ttl -= 1;
+				ppreq.preq_metric += ieee80211_airtime_calc(ni);
+				/*
+				 * 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);
+			}
 			/*
-			 * Check if we can send an intermediate Path Reply.
+			 * Check if we can send an intermediate Path Reply,
+			 * i.e., Target Only bit is not set.
 			 */
 	    		if (!(PREQ_TFLAGS(0) & IEEE80211_MESHPREQ_TFLAGS_TO)) {
 				struct ieee80211_meshprep_ie prep;
@@ -663,33 +672,36 @@ hwmp_recv_preq(struct ieee80211vap *vap,
 				    "intermediate reply for PREQ from %s",
 				    ether_sprintf(preq->preq_origaddr));
 				prep.prep_flags = 0;
-				prep.prep_hopcount = 0;
-				prep.prep_ttl = ms->ms_ttl;
+				prep.prep_hopcount = fi->fi_nhops + 1;
+				prep.prep_ttl = hs->hs_ttl;
 				IEEE80211_ADDR_COPY(&prep.prep_targetaddr,
 				    preq->preq_origaddr);
 				prep.prep_targetseq = fi->fi_seq;
 				prep.prep_lifetime = preq->preq_lifetime;
-				prep.prep_metric = fi->fi_metric;
+				prep.prep_metric = fi->fi_metric +
+				    ieee80211_airtime_calc(ni);
 				IEEE80211_ADDR_COPY(&prep.prep_origaddr,
 				    PREQ_TADDR(0));
 				prep.prep_origseq = hs->hs_seq++;
 				hwmp_send_prep(ni, vap->iv_myaddr,
 				    broadcastaddr, &prep);
 			}
-		} else {
-			fi = hwmp_rt_add(vap, PREQ_TADDR(0));
+		/*
+		 * We have no information about this path,
+		 * propagate the PREQ based on TTL.
+		 */
+		} else if (preq->preq_ttl > 1) {
+			if (fi == NULL) {
+				fi = hwmp_rt_add(vap, PREQ_TADDR(0));
+				fi->fi_metric = preq->preq_metric;
+				fi->fi_lifetime = preq->preq_lifetime;
+			}
 			fi->fi_seq = preq->preq_origseq;
-			fi->fi_metric = preq->preq_metric;
-			fi->fi_lifetime = preq->preq_lifetime;
 			fi->fi_preqid = preq->preq_id;
 
 			IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
 			    "forwarding PREQ from %s",
 			    ether_sprintf(preq->preq_origaddr));
-			/*
-			 * We have no information about this path,
-			 * propagate the PREQ.
-			 */
 			ppreq.preq_hopcount += 1;
 			ppreq.preq_ttl -= 1;
 			ppreq.preq_metric += ieee80211_airtime_calc(ni);
@@ -701,7 +713,6 @@ hwmp_recv_preq(struct ieee80211vap *vap,
 		 */
 		return;
 	}
-		
 
 	/*
 	 * XXX: Proactive PREQ: reply with a proactive PREP to the
@@ -770,7 +781,6 @@ hwmp_recv_prep(struct ieee80211vap *vap,
 	IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
 	    "received PREP from %s", ether_sprintf(prep->prep_origaddr));
 
-	fi = hwmp_rt_find(vap, prep->prep_origaddr);
 	/*
 	 * If it's NOT for us, propagate the PREP if TTL is
 	 * greater than 1.
@@ -795,6 +805,7 @@ hwmp_recv_prep(struct ieee80211vap *vap,
 		return;
 	}
 
+	fi = hwmp_rt_find(vap, prep->prep_origaddr);
 	if (fi != NULL) {
 		/*
 		 * Build the rest of the entry.
@@ -815,7 +826,7 @@ hwmp_recv_prep(struct ieee80211vap *vap,
 	 * XXX: If it's NOT for us and the AE bit is set,
 	 * update the proxy information table.
 	 */
-
+#if 0
 	if (fi != NULL) {
 		struct ieee80211com *ic = vap->iv_ic;
 		struct ifnet *ifp = vap->iv_ifp;
@@ -836,6 +847,7 @@ hwmp_recv_prep(struct ieee80211vap *vap,
 			ifp->if_transmit(ifp, m);
 		}
 	}
+#endif
 }
 
 static inline int
@@ -867,6 +879,31 @@ hwmp_send_prep(struct ieee80211_node *ni
 	    sizeof(struct ieee80211_meshprep_ie));
 }
 
+#define	PERR_DADDR(n)	perr.perr_dests[n].dest_addr
+#define	PERR_DSEQ(n)	perr.perr_dests[n].dest_seq
+void
+ieee80211_hwmp_peerdown(struct ieee80211_node *ni)
+{
+	struct ieee80211vap *vap = ni->ni_vap;
+	struct ieee80211_meshperr_ie perr;
+	struct ieee80211_hwmp_fi *fi;
+
+	fi = hwmp_rt_find(vap, ni->ni_macaddr);
+	if (fi == NULL)
+		return;
+	IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
+	    "%s", "deleting route entry");
+	perr.perr_mode = 0;
+	perr.perr_ndests = 1;
+	IEEE80211_ADDR_COPY(PERR_DADDR(0), fi->fi_dest);
+	PERR_DSEQ(0) = fi->fi_seq;
+	hwmp_rt_del(vap, ni->ni_macaddr);
+	hwmp_send_perr(vap->iv_bss, vap->iv_myaddr, broadcastaddr, &perr);
+}
+#undef	PERR_DADDR
+#undef	PERR_DSEQ
+
+
 #define	PERR_DADDR(n)	perr->perr_dests[n].dest_addr
 #define	PERR_DSEQ(n)	perr->perr_dests[n].dest_seq
 static void
@@ -876,7 +913,7 @@ hwmp_recv_perr(struct ieee80211vap *vap,
 	struct ieee80211_mesh_state *ms = vap->iv_mesh;
 	struct ieee80211_hwmp_fi *fi = NULL;
  	struct ieee80211_meshperr_ie pperr;
-	int i;
+	int i, forward = 0;
 
 	/*
 	 * Acceptance criteria: check if we received a PERR from a
@@ -886,24 +923,29 @@ hwmp_recv_perr(struct ieee80211vap *vap,
 	    ni->ni_mlstate != IEEE80211_NODE_MESH_ESTABLISHED ||
 	    !(ms->ms_flags & IEEE80211_MESHFLAGS_FWD))
 		return;
-
+	/*
+	 * Find all routing entries that match and delete them.
+	 */
 	for (i = 0; i < perr->perr_ndests; i++) {
 		fi = hwmp_rt_find(vap, PERR_DADDR(i));
 		if (fi == NULL)
-			break;
-		if (PERR_DSEQ(i) > fi->fi_seq) {
+			continue;
+		if (PERR_DSEQ(i) >= fi->fi_seq) {
 			hwmp_rt_del(vap, fi->fi_dest);
 			fi = NULL;
+			forward = 1;
 		}
 	}
 	/*
-	 * Propagate the PERR.
+	 * Propagate the PERR if we previously found it on our routing table.
 	 * XXX handle ndest > 1
 	 */
-	IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
-	    "propagating PERR from %s", ether_sprintf(wh->i_addr2));
-	memcpy(&pperr, perr, sizeof(*perr));
-	hwmp_send_perr(vap->iv_bss, vap->iv_myaddr, broadcastaddr, &pperr);
+	if (forward) {
+		IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
+		    "propagating PERR from %s", ether_sprintf(wh->i_addr2));
+		memcpy(&pperr, perr, sizeof(*perr));
+		hwmp_send_perr(vap->iv_bss, vap->iv_myaddr, broadcastaddr, &pperr);
+	}
 }
 #undef	PEER_DADDR
 #undef	PERR_DSEQ
@@ -932,6 +974,7 @@ hwmp_send_perr(struct ieee80211_node *ni
 	 *     [1] category
 	 *     [tlv] mesh path error
 	 */
+	perr->perr_ie = IEEE80211_ELEMID_MESHPERR;
 	return ieee80211_hwmp_send_action(ni, sa, da, (uint8_t *)perr,
 	    sizeof(struct ieee80211_meshperr_ie));
 }
@@ -960,7 +1003,7 @@ hwmp_recv_rann(struct ieee80211vap *vap,
 		 */
 		preq.preq_flags = 0;
 		preq.preq_hopcount = 0;
-		preq.preq_ttl = ms->ms_ttl;
+		preq.preq_ttl = hs->hs_ttl;
 		IEEE80211_ADDR_COPY(&preq.preq_origaddr,
 		    vap->iv_myaddr);
 		preq.preq_origseq = hs->hs_seq++;
@@ -1014,7 +1057,6 @@ struct ieee80211_node *
 ieee80211_hwmp_discover(struct ieee80211vap *vap,
     uint8_t dest[IEEE80211_ADDR_LEN], struct mbuf *m)
 {
-	struct ieee80211_mesh_state *ms = vap->iv_mesh;
 	struct ieee80211_hwmp_state *hs = vap->iv_hwmp;
 	struct ieee80211_hwmp_fi *fi = NULL;
 	struct ieee80211_meshpreq_ie preq;
@@ -1056,7 +1098,7 @@ ieee80211_hwmp_discover(struct ieee80211
 			 */
 			preq.preq_flags = 0;
 			preq.preq_hopcount = 0;
-			preq.preq_ttl = ms->ms_ttl;
+			preq.preq_ttl = hs->hs_ttl;
 			preq.preq_id = fi->fi_preqid;
 			IEEE80211_ADDR_COPY(preq.preq_origaddr, vap->iv_myaddr);
 			preq.preq_origseq = fi->fi_seq;
@@ -1088,6 +1130,7 @@ done:
 	if (ni == NULL && m != NULL) {
 		IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_HWMP,
 		    dest, NULL, "%s", "no valid path to this node");
+#if 0
 		if (sendpreq) {
 			struct ieee80211com *ic = vap->iv_ic;
 			/*
@@ -1101,6 +1144,7 @@ done:
 			ieee80211_ageq_append(&ic->ic_stageq, m,
 			    IEEE80211_INACT_WAIT);
 		} else
+#endif
 			m_freem(m);
 	}
 	return ni;
@@ -1180,6 +1224,9 @@ hwmp_ioctl_get80211(struct ieee80211vap 
 	case IEEE80211_IOC_HWMP_MAXHOPS:
 		ireq->i_val = hs->hs_maxhops;
 		break;
+	case IEEE80211_IOC_HWMP_TTL:
+		ireq->i_val = hs->hs_ttl;
+		break;
 	default:
 		return ENOSYS;
 	}
@@ -1224,6 +1271,11 @@ hwmp_ioctl_set80211(struct ieee80211vap 
 			return EINVAL;
 		hs->hs_maxhops = ireq->i_val;
 		break;
+	case IEEE80211_IOC_HWMP_TTL:
+		if (ireq->i_val <= 0 || ireq->i_val > 255)
+			return EINVAL;
+		hs->hs_ttl = ireq->i_val;
+		break;
 	default:
 		return ENOSYS;
 	}

Modified: projects/mesh11s/sys/net80211/ieee80211_hwmp.h
==============================================================================
--- projects/mesh11s/sys/net80211/ieee80211_hwmp.h	Mon Jun 29 15:23:50 2009	(r195157)
+++ projects/mesh11s/sys/net80211/ieee80211_hwmp.h	Mon Jun 29 15:53:52 2009	(r195158)
@@ -64,6 +64,7 @@ struct ieee80211_hwmp_state {
 	struct mtx		hs_lock;	/* lock for the fi table */
 	int			hs_rootmode;	/* proactive HWMP */
 	uint8_t			hs_maxhops;	/* max hop count */
+	uint8_t			hs_ttl;		/* HWMP ttl */
 };
 
 void	ieee80211_hwmp_vattach(struct ieee80211vap *);
@@ -77,6 +78,7 @@ struct ieee80211_node *ieee80211_hwmp_di
 struct ieee80211_node *
 ieee80211_hwmp_find_txnode(struct ieee80211vap *vap,
     uint8_t dest[IEEE80211_ADDR_LEN]);
+void	ieee80211_hwmp_peerdown(struct ieee80211_node *);
 #endif /* _KERNEL */
 
 #endif /* _NET80211_IEEE80211_HWMP_H_ */

Modified: projects/mesh11s/sys/net80211/ieee80211_ioctl.h
==============================================================================
--- projects/mesh11s/sys/net80211/ieee80211_ioctl.h	Mon Jun 29 15:23:50 2009	(r195157)
+++ projects/mesh11s/sys/net80211/ieee80211_ioctl.h	Mon Jun 29 15:53:52 2009	(r195158)
@@ -669,6 +669,7 @@ struct ieee80211req {
 #define	IEEE80211_IOC_HWMP_CMD		195	/* HWMP table commands */
 #define	IEEE80211_IOC_HWMP_ROOTMODE	196	/* HWMP root mode */
 #define	IEEE80211_IOC_HWMP_MAXHOPS	197	/* number of hops before drop */
+#define	IEEE80211_IOC_HWMP_TTL		198	/* HWMP TTL */
 
 #define	IEEE80211_IOC_TDMA_SLOT		201	/* TDMA: assigned slot */
 #define	IEEE80211_IOC_TDMA_SLOTCNT	202	/* TDMA: slots in bss */

Modified: projects/mesh11s/sys/net80211/ieee80211_mesh.c
==============================================================================
--- projects/mesh11s/sys/net80211/ieee80211_mesh.c	Mon Jun 29 15:23:50 2009	(r195157)
+++ projects/mesh11s/sys/net80211/ieee80211_mesh.c	Mon Jun 29 15:53:52 2009	(r195158)
@@ -285,7 +285,8 @@ mesh_linkchange(struct ieee80211_node *n
 	IEEE80211_NOTE(vap, IEEE80211_MSG_MESH,
 	    ni, "peer link: switching to state %s",
 	    meshlinkstates[ni->ni_mlstate]);
-
+	if (state == IEEE80211_NODE_MESH_HOLDING)
+		ieee80211_hwmp_peerdown(ni);
 }
 
 /*


More information about the svn-src-projects mailing list