Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 29 Sep 2009 12:18:23 +0000 (UTC)
From:      Rui Paulo <rpaulo@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org
Subject:   svn commit: r197614 - stable/8/sys/net80211
Message-ID:  <200909291218.n8TCINmv085038@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: rpaulo
Date: Tue Sep 29 12:18:23 2009
New Revision: 197614
URL: http://svn.freebsd.org/changeset/base/197614

Log:
  Update 802.11s mesh support to draft 3.03. This includes a revised  frame
  format for peering and changes to the PERR frames.
  Note that this is incompatible with the previous code.
  
  Reviewed by:	sam
  Approved by:	re (kib)

Modified:
  stable/8/sys/net80211/ieee80211.h
  stable/8/sys/net80211/ieee80211_hwmp.c
  stable/8/sys/net80211/ieee80211_mesh.c
  stable/8/sys/net80211/ieee80211_mesh.h

Modified: stable/8/sys/net80211/ieee80211.h
==============================================================================
--- stable/8/sys/net80211/ieee80211.h	Tue Sep 29 10:53:06 2009	(r197613)
+++ stable/8/sys/net80211/ieee80211.h	Tue Sep 29 12:18:23 2009	(r197614)
@@ -708,7 +708,7 @@ enum {
 	IEEE80211_ELEMID_VENDOR		= 221,	/* vendor private */
 
 	/*
-	 * 802.11s IEs based on D3.0 spec and were not assigned by
+	 * 802.11s IEs based on D3.03 spec and were not assigned by
 	 * ANA. Beware changing them because some of them are being
 	 * kept compatible with Linux.
 	 */
@@ -726,10 +726,9 @@ enum {
 	IEEE80211_ELEMID_MESHPREQ	= 68,
 	IEEE80211_ELEMID_MESHPREP	= 69,
 	IEEE80211_ELEMID_MESHPERR	= 70,
-	IEEE80211_ELEMID_MESHPU		= 53,
-	IEEE80211_ELEMID_MESHPUC	= 54,
+	IEEE80211_ELEMID_MESHPXU	= 53,
+	IEEE80211_ELEMID_MESHPXUC	= 54,
 	IEEE80211_ELEMID_MESHAH		= 60, /* Abbreviated Handshake */
-	IEEE80211_ELEMID_MESHPEERVER	= 80, /* Peering Protocol Version */
 };
 
 struct ieee80211_tim_ie {
@@ -925,6 +924,9 @@ enum {
 	IEEE80211_REASON_MESH_INVALID_GTK	= 8,	/* 11s */
 	IEEE80211_REASON_MESH_INCONS_PARAMS	= 9,	/* 11s */
 	IEEE80211_REASON_MESH_INVALID_SECURITY	= 10,	/* 11s */
+	IEEE80211_REASON_MESH_PERR_UNSPEC	= 11,	/* 11s */
+	IEEE80211_REASON_MESH_PERR_NO_FI	= 12,	/* 11s */
+	IEEE80211_REASON_MESH_PERR_DEST_UNREACH	= 13,	/* 11s */
 
 	IEEE80211_STATUS_SUCCESS		= 0,
 	IEEE80211_STATUS_UNSPECIFIED		= 1,

Modified: stable/8/sys/net80211/ieee80211_hwmp.c
==============================================================================
--- stable/8/sys/net80211/ieee80211_hwmp.c	Tue Sep 29 10:53:06 2009	(r197613)
+++ stable/8/sys/net80211/ieee80211_hwmp.c	Tue Sep 29 12:18:23 2009	(r197614)
@@ -188,10 +188,7 @@ SYSCTL_PROC(_net_wlan_hwmp, OID_AUTO, ra
 
 #define	IEEE80211_HWMP_DEFAULT_MAXHOPS	31
 
-static	ieee80211_recv_action_func hwmp_recv_action_meshpath_preq;
-static	ieee80211_recv_action_func hwmp_recv_action_meshpath_prep;
-static	ieee80211_recv_action_func hwmp_recv_action_meshpath_perr;
-static	ieee80211_recv_action_func hwmp_recv_action_meshpath_rann;
+static	ieee80211_recv_action_func hwmp_recv_action_meshpath;
 
 static struct ieee80211_mesh_proto_path mesh_proto_hwmp = {
 	.mpp_descr	= "HWMP",
@@ -217,16 +214,10 @@ ieee80211_hwmp_init(void)
 	ieee80211_hwmp_rannint = msecs_to_ticks(1*1000);
 
 	/*
-	 * Register action frame handlers.
+	 * Register action frame handler.
 	 */
 	ieee80211_recv_action_register(IEEE80211_ACTION_CAT_MESHPATH,
-	    IEEE80211_ACTION_MESHPATH_REQ, hwmp_recv_action_meshpath_preq);
-	ieee80211_recv_action_register(IEEE80211_ACTION_CAT_MESHPATH,
-	    IEEE80211_ACTION_MESHPATH_REP, hwmp_recv_action_meshpath_prep);
-	ieee80211_recv_action_register(IEEE80211_ACTION_CAT_MESHPATH,
-	    IEEE80211_ACTION_MESHPATH_ERR, hwmp_recv_action_meshpath_perr);
-	ieee80211_recv_action_register(IEEE80211_ACTION_CAT_MESHPATH,
-	    IEEE80211_ACTION_MESHPATH_RANN, hwmp_recv_action_meshpath_rann);
+	    IEEE80211_ACTION_MESHPATH_SEL, hwmp_recv_action_meshpath);
 
 	/* NB: default is 5 secs per spec */
 	mesh_proto_hwmp.mpp_inact = msecs_to_ticks(5*1000);
@@ -285,17 +276,23 @@ hwmp_newstate(struct ieee80211vap *vap, 
 }
 
 static int
-hwmp_recv_action_meshpath_preq(struct ieee80211_node *ni,
+hwmp_recv_action_meshpath(struct ieee80211_node *ni,
 	const struct ieee80211_frame *wh,
 	const uint8_t *frm, const uint8_t *efrm)
 {
 	struct ieee80211vap *vap = ni->ni_vap;
 	struct ieee80211_meshpreq_ie preq;
+	struct ieee80211_meshprep_ie prep;
+	struct ieee80211_meshperr_ie perr;
+	struct ieee80211_meshrann_ie rann;
 	const uint8_t *iefrm = frm + 2; /* action + code */
+	int found = 0;
 
 	while (efrm - iefrm > 1) {
 		IEEE80211_VERIFY_LENGTH(efrm - iefrm, iefrm[1] + 2, return 0);
-		if (*iefrm == IEEE80211_ELEMID_MESHPREQ) {
+		switch (*iefrm) {
+		case IEEE80211_ELEMID_MESHPREQ:
+		{
 			const struct ieee80211_meshpreq_ie *mpreq =
 			    (const struct ieee80211_meshpreq_ie *) iefrm;
 			/* XXX > 1 target */
@@ -305,7 +302,7 @@ hwmp_recv_action_meshpath_preq(struct ie
 				    IEEE80211_MSG_ACTION | IEEE80211_MSG_HWMP,
 				    wh, NULL, "%s", "PREQ with wrong len");
 				vap->iv_stats.is_rx_mgtdiscard++;
-				return 1;
+				break;
 			}
 			memcpy(&preq, mpreq, sizeof(preq));
 			preq.preq_id = LE_READ_4(&mpreq->preq_id);
@@ -315,28 +312,11 @@ hwmp_recv_action_meshpath_preq(struct ie
 			preq.preq_targets[0].target_seq =
 			    LE_READ_4(&mpreq->preq_targets[0].target_seq);
 			hwmp_recv_preq(vap, ni, wh, &preq);
-			return 0;
+			found++;
+			break;	
 		}
-		iefrm += iefrm[1] + 2;
-	}
-	IEEE80211_DISCARD(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_HWMP,
-	    wh, NULL, "%s", "PREQ without IE");
-	vap->iv_stats.is_rx_mgtdiscard++;
-	return 0;
-}
-
-static int
-hwmp_recv_action_meshpath_prep(struct ieee80211_node *ni,
-	const struct ieee80211_frame *wh,
-	const uint8_t *frm, const uint8_t *efrm)
-{
-	struct ieee80211vap *vap = ni->ni_vap;
-	struct ieee80211_meshprep_ie prep;
-	const uint8_t *iefrm = frm + 2; /* action + code */
-
-	while (efrm - iefrm > 1) {
-		IEEE80211_VERIFY_LENGTH(efrm - iefrm, iefrm[1] + 2, return 0);
-		if (*iefrm == IEEE80211_ELEMID_MESHPREP) {
+		case IEEE80211_ELEMID_MESHPREP:
+		{
 			const struct ieee80211_meshprep_ie *mprep =
 			    (const struct ieee80211_meshprep_ie *) iefrm;
 			if (mprep->prep_len !=
@@ -345,7 +325,7 @@ hwmp_recv_action_meshpath_prep(struct ie
 				    IEEE80211_MSG_ACTION | IEEE80211_MSG_HWMP,
 				    wh, NULL, "%s", "PREP with wrong len");
 				vap->iv_stats.is_rx_mgtdiscard++;
-				return 1;
+				break;
 			}
 			memcpy(&prep, mprep, sizeof(prep));
 			prep.prep_targetseq = LE_READ_4(&mprep->prep_targetseq);
@@ -353,28 +333,11 @@ hwmp_recv_action_meshpath_prep(struct ie
 			prep.prep_metric = LE_READ_4(&mprep->prep_metric);
 			prep.prep_origseq = LE_READ_4(&mprep->prep_origseq);
 			hwmp_recv_prep(vap, ni, wh, &prep);
-			return 0;
+			found++;
+			break;
 		}
-		iefrm += iefrm[1] + 2;
-	}
-	IEEE80211_DISCARD(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_HWMP,
-	    wh, NULL, "%s", "PREP without IE");
-	vap->iv_stats.is_rx_mgtdiscard++;
-	return 0;
-}
-
-static int
-hwmp_recv_action_meshpath_perr(struct ieee80211_node *ni,
-	const struct ieee80211_frame *wh,
-	const uint8_t *frm, const uint8_t *efrm)
-{
-	struct ieee80211_meshperr_ie perr;
-	struct ieee80211vap *vap = ni->ni_vap;
-	const uint8_t *iefrm = frm + 2; /* action + code */
-
-	while (efrm - iefrm > 1) {
-		IEEE80211_VERIFY_LENGTH(efrm - iefrm, iefrm[1] + 2, return 0);
-		if (*iefrm == IEEE80211_ELEMID_MESHPERR) {
+		case IEEE80211_ELEMID_MESHPERR:
+		{
 			const struct ieee80211_meshperr_ie *mperr =
 			    (const struct ieee80211_meshperr_ie *) iefrm;
 			/* XXX > 1 target */
@@ -384,34 +347,17 @@ hwmp_recv_action_meshpath_perr(struct ie
 				    IEEE80211_MSG_ACTION | IEEE80211_MSG_HWMP,
 				    wh, NULL, "%s", "PERR with wrong len");
 				vap->iv_stats.is_rx_mgtdiscard++;
-				return 1;
+				break;
 			}
 			memcpy(&perr, mperr, sizeof(perr));
 			perr.perr_dests[0].dest_seq =
 			    LE_READ_4(&mperr->perr_dests[0].dest_seq);
 			hwmp_recv_perr(vap, ni, wh, &perr);
-			return 0;
+			found++;
+			break;
 		}
-		iefrm += iefrm[1] + 2;
-	}
-	IEEE80211_DISCARD(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_HWMP,
-	    wh, NULL, "%s", "PERR without IE");
-	vap->iv_stats.is_rx_mgtdiscard++;
-	return 0;
-}
-
-static int
-hwmp_recv_action_meshpath_rann(struct ieee80211_node *ni,
-	const struct ieee80211_frame *wh,
-	const uint8_t *frm, const uint8_t *efrm)
-{
-	struct ieee80211vap *vap = ni->ni_vap;
-	struct ieee80211_meshrann_ie rann;
-	const uint8_t *iefrm = frm + 2; /* action + code */
-
-	while (efrm - iefrm > 1) {
-		IEEE80211_VERIFY_LENGTH(efrm - iefrm, iefrm[1] + 2, return 0);
-		if (*iefrm == IEEE80211_ELEMID_MESHRANN) {
+		case IEEE80211_ELEMID_MESHRANN:
+		{
 			const struct ieee80211_meshrann_ie *mrann =
 			    (const struct ieee80211_meshrann_ie *) iefrm;
 			if (mrann->rann_len !=
@@ -426,13 +372,18 @@ hwmp_recv_action_meshpath_rann(struct ie
 			rann.rann_seq = LE_READ_4(&mrann->rann_seq);
 			rann.rann_metric = LE_READ_4(&mrann->rann_metric);
 			hwmp_recv_rann(vap, ni, wh, &rann);
-			return 0;
+			found++;
+			break;
+		}
 		}
 		iefrm += iefrm[1] + 2;
 	}
-	IEEE80211_DISCARD(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_HWMP,
-	    wh, NULL, "%s", "RANN without IE");
-	vap->iv_stats.is_rx_mgtdiscard++;
+	if (!found) {
+		IEEE80211_DISCARD(vap,
+		    IEEE80211_MSG_ACTION | IEEE80211_MSG_HWMP,
+		    wh, NULL, "%s", "PATH SEL action without IE");
+		vap->iv_stats.is_rx_mgtdiscard++;
+	}
 	return 0;
 }
 
@@ -480,24 +431,21 @@ hwmp_send_action(struct ieee80211_node *
 		return ENOMEM;
 	}
 	*frm++ = IEEE80211_ACTION_CAT_MESHPATH;
+	*frm++ = IEEE80211_ACTION_MESHPATH_SEL;
 	switch (*ie) {
 	case IEEE80211_ELEMID_MESHPREQ:
-		*frm++ = IEEE80211_ACTION_MESHPATH_REQ;
 		frm = hwmp_add_meshpreq(frm,
 		    (struct ieee80211_meshpreq_ie *)ie);
 		break;
 	case IEEE80211_ELEMID_MESHPREP:
-		*frm++ = IEEE80211_ACTION_MESHPATH_REP;
 		frm = hwmp_add_meshprep(frm,
 		    (struct ieee80211_meshprep_ie *)ie);
 		break;
 	case IEEE80211_ELEMID_MESHPERR:
-		*frm++ = IEEE80211_ACTION_MESHPATH_ERR;
 		frm = hwmp_add_meshperr(frm,
 		    (struct ieee80211_meshperr_ie *)ie);
 		break;
 	case IEEE80211_ELEMID_MESHRANN:
-		*frm++ = IEEE80211_ACTION_MESHPATH_RANN;
 		frm = hwmp_add_meshrann(frm,
 		    (struct ieee80211_meshrann_ie *)ie);
 		break;
@@ -528,6 +476,11 @@ hwmp_send_action(struct ieee80211_node *
 	return ic->ic_raw_xmit(ni, m, &params);
 }
 
+#define ADDSHORT(frm, v) do {		\
+	frm[0] = (v) & 0xff;		\
+	frm[1] = (v) >> 8;		\
+	frm += 2;			\
+} while (0)
 #define ADDWORD(frm, v) do {		\
 	LE_WRITE_4(frm, v);		\
 	frm += 4;			\
@@ -592,12 +545,14 @@ hwmp_add_meshperr(uint8_t *frm, const st
 	*frm++ = IEEE80211_ELEMID_MESHPERR;
 	*frm++ = sizeof(struct ieee80211_meshperr_ie) - 2 +
 	    (perr->perr_ndests - 1) * sizeof(*perr->perr_dests);
-	*frm++ = perr->perr_mode;
+	*frm++ = perr->perr_ttl;
 	*frm++ = perr->perr_ndests;
 	for (i = 0; i < perr->perr_ndests; i++) {
+		*frm += perr->perr_dests[i].dest_flags;
 		IEEE80211_ADDR_COPY(frm, perr->perr_dests[i].dest_addr);
 		frm += 6;
 		ADDWORD(frm, perr->perr_dests[i].dest_seq);
+		ADDSHORT(frm, perr->perr_dests[i].dest_rcode);
 	}
 	return frm;
 }
@@ -1138,12 +1093,15 @@ hwmp_send_prep(struct ieee80211_node *ni
 	    sizeof(struct ieee80211_meshprep_ie));
 }
 
+#define	PERR_DFLAGS(n)	perr.perr_dests[n].dest_flags
 #define	PERR_DADDR(n)	perr.perr_dests[n].dest_addr
 #define	PERR_DSEQ(n)	perr.perr_dests[n].dest_seq
+#define	PERR_DRCODE(n)	perr.perr_dests[n].dest_rcode
 static void
 hwmp_peerdown(struct ieee80211_node *ni)
 {
 	struct ieee80211vap *vap = ni->ni_vap;
+	struct ieee80211_mesh_state *ms = vap->iv_mesh;
 	struct ieee80211_meshperr_ie perr;
 	struct ieee80211_mesh_route *rt;
 	struct ieee80211_hwmp_route *hr;
@@ -1154,19 +1112,27 @@ hwmp_peerdown(struct ieee80211_node *ni)
 	hr = IEEE80211_MESH_ROUTE_PRIV(rt, struct ieee80211_hwmp_route);
 	IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
 	    "%s", "delete route entry");
-	perr.perr_mode = 0;
+	perr.perr_ttl = ms->ms_ttl;
 	perr.perr_ndests = 1;
+	if (hr->hr_seq == 0)
+		PERR_DFLAGS(0) |= IEEE80211_MESHPERR_DFLAGS_USN;
+	PERR_DFLAGS(0) |= IEEE80211_MESHPERR_DFLAGS_RC;
 	IEEE80211_ADDR_COPY(PERR_DADDR(0), rt->rt_dest);
 	PERR_DSEQ(0) = hr->hr_seq;
+	PERR_DRCODE(0) = IEEE80211_REASON_MESH_PERR_DEST_UNREACH;
 	/* 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_DFLAGS
 #undef	PERR_DADDR
 #undef	PERR_DSEQ
+#undef	PERR_DRCODE
 
+#define	PERR_DFLAGS(n)	perr->perr_dests[n].dest_flags
 #define	PERR_DADDR(n)	perr->perr_dests[n].dest_addr
 #define	PERR_DSEQ(n)	perr->perr_dests[n].dest_seq
+#define	PERR_DRCODE(n)	perr->perr_dests[n].dest_rcode
 static void
 hwmp_recv_perr(struct ieee80211vap *vap, struct ieee80211_node *ni,
     const struct ieee80211_frame *wh, const struct ieee80211_meshperr_ie *perr)
@@ -1192,9 +1158,9 @@ hwmp_recv_perr(struct ieee80211vap *vap,
 		rt = ieee80211_mesh_rt_find(vap, PERR_DADDR(i));
 		if (rt == NULL)
 			continue;
-		hr = IEEE80211_MESH_ROUTE_PRIV(rt,
-		    struct ieee80211_hwmp_route);
-		if (HWMP_SEQ_GEQ(PERR_DSEQ(i), hr->hr_seq)) {
+		hr = IEEE80211_MESH_ROUTE_PRIV(rt, struct ieee80211_hwmp_route);
+		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);
 			rt = NULL;
@@ -1205,10 +1171,11 @@ hwmp_recv_perr(struct ieee80211vap *vap,
 	 * Propagate the PERR if we previously found it on our routing table.
 	 * XXX handle ndest > 1
 	 */
-	if (forward) {
+	if (forward && perr->perr_ttl > 1) {
 		IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
 		    "propagate PERR from %s", ether_sprintf(wh->i_addr2));
 		memcpy(&pperr, perr, sizeof(*perr));
+		pperr.perr_ttl--;
 		hwmp_send_perr(vap->iv_bss, vap->iv_myaddr, broadcastaddr,
 		    &pperr);
 	}

Modified: stable/8/sys/net80211/ieee80211_mesh.c
==============================================================================
--- stable/8/sys/net80211/ieee80211_mesh.c	Tue Sep 29 10:53:06 2009	(r197613)
+++ stable/8/sys/net80211/ieee80211_mesh.c	Tue Sep 29 12:18:23 2009	(r197614)
@@ -87,10 +87,10 @@ static void	mesh_peer_timeout_backoff(st
 static void	mesh_peer_timeout_cb(void *);
 static __inline void
 		mesh_peer_timeout_stop(struct ieee80211_node *);
-static int	mesh_verify_meshpeerver(struct ieee80211vap *, const uint8_t *);
 static int	mesh_verify_meshid(struct ieee80211vap *, const uint8_t *);
 static int	mesh_verify_meshconf(struct ieee80211vap *, const uint8_t *);
-static int	mesh_verify_meshpeer(struct ieee80211vap *, const uint8_t *);
+static int	mesh_verify_meshpeer(struct ieee80211vap *, uint8_t,
+    		    const uint8_t *);
 uint32_t	mesh_airtime_calc(struct ieee80211_node *);
 
 /*
@@ -1544,19 +1544,16 @@ static const struct ieee80211_meshpeer_i
 mesh_parse_meshpeering_action(struct ieee80211_node *ni,
 	const struct ieee80211_frame *wh,	/* XXX for VERIFY_LENGTH */
 	const uint8_t *frm, const uint8_t *efrm,
-	struct ieee80211_meshpeer_ie *mp)
+	struct ieee80211_meshpeer_ie *mp, uint8_t subtype)
 {
 	struct ieee80211vap *vap = ni->ni_vap;
 	const struct ieee80211_meshpeer_ie *mpie;
-	const uint8_t *meshid, *meshconf, *meshpeerver, *meshpeer;
+	const uint8_t *meshid, *meshconf, *meshpeer;
 
-	meshid = meshconf = meshpeerver = meshpeer = NULL;
+	meshid = meshconf = meshpeer = NULL;
 	while (efrm - frm > 1) {
 		IEEE80211_VERIFY_LENGTH(efrm - frm, frm[1] + 2, return NULL);
 		switch (*frm) {
-		case IEEE80211_ELEMID_MESHPEERVER:
-			meshpeerver = frm;
-			break;
 		case IEEE80211_ELEMID_MESHID:
 			meshid = frm;
 			break;
@@ -1567,12 +1564,10 @@ mesh_parse_meshpeering_action(struct iee
 			meshpeer = frm;
 			mpie = (const struct ieee80211_meshpeer_ie *) frm;
 			memset(mp, 0, sizeof(*mp));
-			mp->peer_subtype = mpie->peer_subtype;
 			mp->peer_llinkid = LE_READ_2(&mpie->peer_llinkid);
 			/* NB: peer link ID is optional on these frames */
-			if (mpie->peer_subtype ==
-			    IEEE80211_MESH_PEER_LINK_CLOSE &&
-			    mpie->peer_len == 5) {
+			if (subtype == IEEE80211_MESH_PEER_LINK_CLOSE &&
+			    mpie->peer_len == 8) {
 				mp->peer_linkid = 0;
 				mp->peer_rcode = LE_READ_2(&mpie->peer_linkid);
 			} else {
@@ -1589,12 +1584,12 @@ mesh_parse_meshpeering_action(struct iee
 	 * close subtype don't have a Mesh Configuration IE.
 	 * If if fails validation, close the peer link.
 	 */
-	KASSERT(meshpeer != NULL && mp->peer_subtype !=
-	    IEEE80211_ACTION_MESHPEERING_CLOSE, ("parsing close action"));
+	KASSERT(meshpeer != NULL &&
+	    subtype != IEEE80211_ACTION_MESHPEERING_CLOSE,
+	    ("parsing close action"));
 
-	if (mesh_verify_meshpeerver(vap, meshpeerver) ||
-	    mesh_verify_meshid(vap, meshid) ||
-	    mesh_verify_meshpeer(vap, meshpeer) ||
+	if (mesh_verify_meshid(vap, meshid) ||
+	    mesh_verify_meshpeer(vap, subtype, meshpeer) ||
 	    mesh_verify_meshconf(vap, meshconf)) {
 		uint16_t args[3];
 
@@ -1638,7 +1633,8 @@ mesh_recv_action_meshpeering_open(struct
 	uint16_t args[3];
 
 	/* +2+2 for action + code + capabilites */
-	meshpeer = mesh_parse_meshpeering_action(ni, wh, frm+2+2, efrm, &ie);
+	meshpeer = mesh_parse_meshpeering_action(ni, wh, frm+2+2, efrm, &ie,
+	    IEEE80211_ACTION_MESHPEERING_OPEN);
 	if (meshpeer == NULL) {
 		return 0;
 	}
@@ -1770,7 +1766,8 @@ mesh_recv_action_meshpeering_confirm(str
 	uint16_t args[3];
 
 	/* +2+2+2+2 for action + code + capabilites + status code + AID */
-	meshpeer = mesh_parse_meshpeering_action(ni, wh, frm+2+2+2+2, efrm, &ie);
+	meshpeer = mesh_parse_meshpeering_action(ni, wh, frm+2+2+2+2, efrm, &ie,
+	    IEEE80211_ACTION_MESHPEERING_CONFIRM);
 	if (meshpeer == NULL) {
 		return 0;
 	}
@@ -1933,7 +1930,6 @@ mesh_send_action_meshpeering_open(struct
 	    ic->ic_headroom + sizeof(struct ieee80211_frame),
 	    sizeof(uint16_t)	/* action+category */
 	    + sizeof(uint16_t)	/* capabilites */
-	    + sizeof(struct ieee80211_meshpeerver_ie)	 
 	    + 2 + IEEE80211_RATE_SIZE	 
 	    + 2 + (IEEE80211_RATE_MAXSIZE - IEEE80211_RATE_SIZE)	 
 	    + 2 + IEEE80211_MESHID_LEN
@@ -1946,7 +1942,6 @@ mesh_send_action_meshpeering_open(struct
 		 *   [1] category
 		 *   [1] action
 		 *   [2] capabilities
-		 *   [tlv] mesh peer protocol version
 		 *   [tlv] rates
 		 *   [tlv] xrates
 		 *   [tlv] mesh id
@@ -1956,7 +1951,6 @@ mesh_send_action_meshpeering_open(struct
 		*frm++ = category;
 		*frm++ = action;
 		ADDSHORT(frm, ieee80211_getcapinfo(vap, ni->ni_chan));
-		frm = ieee80211_add_meshpeerver(frm, vap);
 		rs = ieee80211_get_suprates(ic, ic->ic_curchan);
 		frm = ieee80211_add_rates(frm, rs);
 		frm = ieee80211_add_xrates(frm, rs);
@@ -1999,7 +1993,6 @@ mesh_send_action_meshpeering_confirm(str
 	    + sizeof(uint16_t)	/* capabilites */
 	    + sizeof(uint16_t)	/* status code */
 	    + sizeof(uint16_t)	/* AID */
-	    + sizeof(struct ieee80211_meshpeerver_ie)	 
 	    + 2 + IEEE80211_RATE_SIZE	 
 	    + 2 + (IEEE80211_RATE_MAXSIZE - IEEE80211_RATE_SIZE)	 
 	    + 2 + IEEE80211_MESHID_LEN
@@ -2014,7 +2007,6 @@ mesh_send_action_meshpeering_confirm(str
 		 *   [2] capabilities
 		 *   [2] status code
 		 *   [2] association id (peer ID)
-		 *   [tlv] mesh peer protocol version
 		 *   [tlv] rates
 		 *   [tlv] xrates
 		 *   [tlv] mesh id
@@ -2026,7 +2018,6 @@ mesh_send_action_meshpeering_confirm(str
 		ADDSHORT(frm, ieee80211_getcapinfo(vap, ni->ni_chan));
 		ADDSHORT(frm, 0);		/* status code */
 		ADDSHORT(frm, args[1]);		/* AID */
-		frm = ieee80211_add_meshpeerver(frm, vap);
 		rs = ieee80211_get_suprates(ic, ic->ic_curchan);
 		frm = ieee80211_add_rates(frm, rs);
 		frm = ieee80211_add_xrates(frm, rs);
@@ -2067,7 +2058,6 @@ mesh_send_action_meshpeering_close(struc
 	    ic->ic_headroom + sizeof(struct ieee80211_frame),
 	    sizeof(uint16_t)	/* action+category */
 	    + sizeof(uint16_t)	/* reason code */
-	    + sizeof(struct ieee80211_meshpeerver_ie)
 	    + 2 + IEEE80211_MESHID_LEN
 	    + sizeof(struct ieee80211_meshpeer_ie) 
 	);
@@ -2077,14 +2067,12 @@ mesh_send_action_meshpeering_close(struc
 		 *   [1] category
 		 *   [1] action
 		 *   [2] reason code
-		 *   [tlv] mesh peer protocol version
 		 *   [tlv] mesh id
 		 *   [tlv] mesh peer link mgmt
 		 */
 		*frm++ = category;
 		*frm++ = action;
 		ADDSHORT(frm, args[2]);		/* reason code */
-		frm = ieee80211_add_meshpeerver(frm, vap);
 		frm = ieee80211_add_meshid(frm, vap);
 		frm = ieee80211_add_meshpeer(frm,
 		    IEEE80211_MESH_PEER_LINK_CLOSE,
@@ -2279,19 +2267,6 @@ mesh_peer_timeout_cb(void *arg)
 }
 
 static int
-mesh_verify_meshpeerver(struct ieee80211vap *vap, const uint8_t *ie)
-{
-	static const uint8_t peer[4] = IEEE80211_MESHPEERVER_PEER;
-	const struct ieee80211_meshpeerver_ie *meshpeerver =
-	    (const struct ieee80211_meshpeerver_ie *) ie;
-
-	if (meshpeerver->peerver_len !=
-	    sizeof(struct ieee80211_meshpeerver_ie) - 2)
-		return 1;
-	return memcmp(meshpeerver->peerver_proto, peer, 4);
-}
-
-static int
 mesh_verify_meshid(struct ieee80211vap *vap, const uint8_t *ie)
 {
 	struct ieee80211_mesh_state *ms = vap->iv_mesh;
@@ -2364,26 +2339,28 @@ mesh_verify_meshconf(struct ieee80211vap
 }
 
 static int
-mesh_verify_meshpeer(struct ieee80211vap *vap, const uint8_t *ie)
+mesh_verify_meshpeer(struct ieee80211vap *vap, uint8_t subtype,
+    const uint8_t *ie)
 {
 	const struct ieee80211_meshpeer_ie *meshpeer =
 	    (const struct ieee80211_meshpeer_ie *) ie;
 
-	if (meshpeer == NULL)
+	if (meshpeer == NULL || meshpeer->peer_len < 6 ||
+	    meshpeer->peer_len > 10)
 		return 1;
-	switch (meshpeer->peer_subtype) {
+	switch (subtype) {
 	case IEEE80211_MESH_PEER_LINK_OPEN:
-		if (meshpeer->peer_len != 3)
+		if (meshpeer->peer_len != 6)
 			return 1;
 		break;
 	case IEEE80211_MESH_PEER_LINK_CONFIRM:
-		if (meshpeer->peer_len != 5)
+		if (meshpeer->peer_len != 8)
 			return 1;
 		break;
 	case IEEE80211_MESH_PEER_LINK_CLOSE:
-		if (meshpeer->peer_len < 5)
+		if (meshpeer->peer_len < 8)
 			return 1;
-		if (meshpeer->peer_len == 5 && meshpeer->peer_linkid != 0)
+		if (meshpeer->peer_len == 8 && meshpeer->peer_linkid != 0)
 			return 1;
 		if (meshpeer->peer_rcode == 0)
 			return 1;
@@ -2449,53 +2426,40 @@ ieee80211_add_meshconf(uint8_t *frm, str
 }
 
 /*
- * Add a Mesh Peer Protocol IE to a frame.
- * XXX: needs to grow support for Abbreviated Handshake
- */
-uint8_t *
-ieee80211_add_meshpeerver(uint8_t *frm, struct ieee80211vap *vap)
-{
-	static struct ieee80211_meshpeerver_ie ie = {
-		.peerver_ie 	= IEEE80211_ELEMID_MESHPEERVER,
-		.peerver_len 	= 4,
-		.peerver_proto	= IEEE80211_MESHPEERVER_PEER,
-	};
-
-	KASSERT(vap->iv_opmode == IEEE80211_M_MBSS, ("not a MBSS vap"));
-
-	memcpy(frm, &ie, sizeof(ie));
-	return frm + sizeof(ie);
-}
-
-/*
  * Add a Mesh Peer Management IE to a frame.
  */
 uint8_t *
 ieee80211_add_meshpeer(uint8_t *frm, uint8_t subtype, uint16_t localid,
     uint16_t peerid, uint16_t reason)
 {
+	/* XXX change for AH */
+	static const uint8_t meshpeerproto[4] = IEEE80211_MESH_PEER_PROTO;
+
 	KASSERT(localid != 0, ("localid == 0"));
 
 	*frm++ = IEEE80211_ELEMID_MESHPEER;
 	switch (subtype) {
 	case IEEE80211_MESH_PEER_LINK_OPEN:
-		*frm++ = 3;		/* length */
-		*frm++ = subtype;
+		*frm++ = 6;		/* length */
+		memcpy(frm, meshpeerproto, 4);
+		frm += 4;
 		ADDSHORT(frm, localid);	/* local ID */
 		break;
 	case IEEE80211_MESH_PEER_LINK_CONFIRM:
 		KASSERT(peerid != 0, ("sending peer confirm without peer id"));
-		*frm++ = 5;		/* length */
-		*frm++ = subtype;
+		*frm++ = 8;		/* length */
+		memcpy(frm, meshpeerproto, 4);
+		frm += 4;
 		ADDSHORT(frm, localid);	/* local ID */
 		ADDSHORT(frm, peerid);	/* peer ID */
 		break;
 	case IEEE80211_MESH_PEER_LINK_CLOSE:
 		if (peerid)
-			*frm++ = 7;	/* length */
+			*frm++ = 10;	/* length */
 		else
-			*frm++ = 5;	/* length */
-		*frm++ = subtype;
+			*frm++ = 8;	/* length */
+		memcpy(frm, meshpeerproto, 4);
+		frm += 4;
 		ADDSHORT(frm, localid);	/* local ID */
 		if (peerid)
 			ADDSHORT(frm, peerid);	/* peer ID */

Modified: stable/8/sys/net80211/ieee80211_mesh.h
==============================================================================
--- stable/8/sys/net80211/ieee80211_mesh.h	Tue Sep 29 10:53:06 2009	(r197613)
+++ stable/8/sys/net80211/ieee80211_mesh.h	Tue Sep 29 12:18:23 2009	(r197614)
@@ -34,7 +34,7 @@
 #define	IEEE80211_MESH_DEFAULT_TTL	31
 
 /*
- * NB: all structures are__packed  so sizeof works on arm, et. al.
+ * NB: all structures are __packed  so sizeof works on arm, et. al.
  */
 /*
  * 802.11s Information Elements.
@@ -116,28 +116,11 @@ struct ieee80211_meshcngst_ie {
 					   AC_BE, AC_VI, AC_VO */
 } __packed;
 
-/* Peer Version */
-struct ieee80211_meshpeerver_ie {
-	uint8_t		peerver_ie;	/* IEEE80211_ELEMID_MESHPEERVER */
-	uint8_t		peerver_len;
-	uint8_t		peerver_proto[4];
-} __packed;
-/* Mesh Peering Management Protocol */
-#define	IEEE80211_MESHPEERVER_PEER_OUI		0x00, 0x0f, 0xac
-#define	IEEE80211_MESHPEERVER_PEER_VALUE	0x2a
-#define	IEEE80211_MESHPEERVER_PEER	{ IEEE80211_MESHPEERVER_PEER_OUI, \
-					  IEEE80211_MESHPEERVER_PEER_VALUE }
-/* Abbreviated Handshake Protocol */
-#define	IEEE80211_MESHPEERVER_AH_OUI		0x00, 0x0f, 0xac
-#define	IEEE80211_MESHPEERVER_AH_VALUE		0x2b
-#define	IEEE80211_MESHPEERVER_AH	{ IEEE80211_MESHPEERVER_AH_OUI, \
-					  IEEE80211_MESHPEERVER_AH_VALUE }
-
 /* Peer Link Management */
 struct ieee80211_meshpeer_ie {
 	uint8_t		peer_ie;	/* IEEE80211_ELEMID_MESHPEER */
 	uint8_t		peer_len;
-	uint8_t		peer_subtype;
+	uint8_t		peer_proto[4];	/* Peer Management Protocol */
 	uint16_t	peer_llinkid;	/* Local Link ID */
 	uint16_t	peer_linkid;	/* Peer Link ID */
 	uint16_t	peer_rcode;
@@ -150,6 +133,16 @@ enum {
 	/* values 3-255 are reserved */
 };
 
+/* Mesh Peering Management Protocol */
+#define	IEEE80211_MESH_PEER_PROTO_OUI		0x00, 0x0f, 0xac
+#define	IEEE80211_MESH_PEER_PROTO_VALUE		0x2a
+#define	IEEE80211_MESH_PEER_PROTO	{ IEEE80211_MESH_PEER_PROTO_OUI, \
+					  IEEE80211_MESH_PEER_PROTO_VALUE }
+/* Abbreviated Handshake Protocol */
+#define	IEEE80211_MESH_PEER_PROTO_AH_OUI	0x00, 0x0f, 0xac
+#define	IEEE80211_MESH_PEER_PROTO_AH_VALUE	0x2b
+#define	IEEE80211_MESH_PEER_PROTO_AH	{ IEEE80211_MESH_PEER_PROTO_AH_OUI, \
+					  IEEE80211_MESH_PEER_PROTO_AH_VALUE }
 #ifdef notyet
 /* Mesh Channel Switch Annoucement */
 struct ieee80211_meshcsa_ie {
@@ -256,11 +249,15 @@ struct ieee80211_meshprep_ie {
 struct ieee80211_meshperr_ie {
 	uint8_t		perr_ie;	/* IEEE80211_ELEMID_MESHPERR */
 	uint8_t		perr_len;
-	uint8_t		perr_mode;	/* NB: reserved */
+	uint8_t		perr_ttl;
 	uint8_t		perr_ndests;	/* Number of Destinations */
 	struct {
+		uint8_t		dest_flags;
+#define	IEEE80211_MESHPERR_DFLAGS_USN	0x01
+#define	IEEE80211_MESHPERR_DFLAGS_RC	0x02
 		uint8_t		dest_addr[IEEE80211_ADDR_LEN];
 		uint32_t	dest_seq;	/* HWMP Sequence Number */
+		uint16_t	dest_rcode;
 	} __packed perr_dests[1];		/* NB: variable size */
 } __packed;
 
@@ -310,14 +307,11 @@ enum {
 };
 
 /*
- * Mesh Path Selection Action codes.
+ * Mesh Path Selection Action code.
  */
 enum {
-	IEEE80211_ACTION_MESHPATH_REQ	= 0,
-	IEEE80211_ACTION_MESHPATH_REP	= 1,
-	IEEE80211_ACTION_MESHPATH_ERR	= 2,
-	IEEE80211_ACTION_MESHPATH_RANN	= 3,
-	/* 4-255 reserved */
+	IEEE80211_ACTION_MESHPATH_SEL	= 0,
+	/* 1-255 reserved */
 };
 
 /*
@@ -479,7 +473,6 @@ int		ieee80211_mesh_register_proto_path(
 int		ieee80211_mesh_register_proto_metric(const
 		    struct ieee80211_mesh_proto_metric *);
 
-uint8_t *	ieee80211_add_meshpeerver(uint8_t *, struct ieee80211vap *);
 uint8_t *	ieee80211_add_meshid(uint8_t *, struct ieee80211vap *);
 uint8_t *	ieee80211_add_meshconf(uint8_t *, struct ieee80211vap *);
 uint8_t *	ieee80211_add_meshpeer(uint8_t *, uint8_t, uint16_t, uint16_t,



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200909291218.n8TCINmv085038>