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

Rui Paulo rpaulo at FreeBSD.org
Thu May 14 17:04:01 UTC 2009


Author: rpaulo
Date: Thu May 14 17:04:00 2009
New Revision: 192111
URL: http://svn.freebsd.org/changeset/base/192111

Log:
  * Change the send action API while keeping ABI to support passing a fixed
  list of arguments or a pointer.
  * Ignore action frames for peers without an established link
  * s/ieee80211_meshcontrol/ieee80211_meshcntl/
  * Parse mesh path request frames and send a path reply if it's destined
  to us.
  
  Sponsored by:	The FreeBSD Foundation

Modified:
  projects/mesh11s/sys/net80211/ieee80211_ht.c
  projects/mesh11s/sys/net80211/ieee80211_mesh.c
  projects/mesh11s/sys/net80211/ieee80211_mesh.h
  projects/mesh11s/sys/net80211/ieee80211_output.c
  projects/mesh11s/sys/net80211/ieee80211_proto.h
  projects/mesh11s/sys/net80211/ieee80211_var.h

Modified: projects/mesh11s/sys/net80211/ieee80211_ht.c
==============================================================================
--- projects/mesh11s/sys/net80211/ieee80211_ht.c	Thu May 14 16:56:56 2009	(r192110)
+++ projects/mesh11s/sys/net80211/ieee80211_ht.c	Thu May 14 17:04:00 2009	(r192111)
@@ -1577,7 +1577,7 @@ ieee80211_aggr_recv_action(struct ieee80
 	struct ieee80211_tx_ampdu *tap;
 	uint8_t dialogtoken, policy;
 	uint16_t baparamset, batimeout, baseqctl, code;
-	uint16_t args[4];
+	union ieee80211_send_action_args vargs;
 	int tid, ac, bufsiz;
 
 	ia = (const struct ieee80211_action *) frm;
@@ -1606,7 +1606,7 @@ ieee80211_aggr_recv_action(struct ieee80
 			rap = &ni->ni_rx_ampdu[tid];
 
 			/* Send ADDBA response */
-			args[0] = dialogtoken;
+			vargs.fixedarg[0] = dialogtoken;
 			/*
 			 * NB: We ack only if the sta associated with HT and
 			 * the ap is configured to do AMPDU rx (the latter
@@ -1618,7 +1618,7 @@ ieee80211_aggr_recv_action(struct ieee80
 				ic->ic_ampdu_rx_start(ni, rap,
 				    baparamset, batimeout, baseqctl);
 
-				args[1] = IEEE80211_STATUS_SUCCESS;
+				vargs.fixedarg[1] = IEEE80211_STATUS_SUCCESS;
 			} else {
 				IEEE80211_NOTE(vap,
 				    IEEE80211_MSG_ACTION | IEEE80211_MSG_11N,
@@ -1627,16 +1627,18 @@ ieee80211_aggr_recv_action(struct ieee80
 				       "administratively disabled" :
 				       "not negotiated for station");
 				vap->iv_stats.is_addba_reject++;
-				args[1] = IEEE80211_STATUS_UNSPECIFIED;
+				vargs.fixedarg[1] =
+				    IEEE80211_STATUS_UNSPECIFIED;
 			}
 			/* XXX honor rap flags? */
-			args[2] = IEEE80211_BAPS_POLICY_IMMEDIATE
+			vargs.fixedarg[2] =
+				  IEEE80211_BAPS_POLICY_IMMEDIATE
 				| SM(tid, IEEE80211_BAPS_TID)
 				| SM(rap->rxa_wnd, IEEE80211_BAPS_BUFSIZ)
 				;
-			args[3] = 0;
+			vargs.fixedarg[3] = 0;
 			ic->ic_send_action(ni, IEEE80211_ACTION_CAT_BA,
-				IEEE80211_ACTION_BA_ADDBA_RESPONSE, args);
+				IEEE80211_ACTION_BA_ADDBA_RESPONSE, vargs);
 			return;
 
 		case IEEE80211_ACTION_BA_ADDBA_RESPONSE:
@@ -1777,9 +1779,9 @@ ieee80211_ampdu_request(struct ieee80211
 	struct ieee80211_tx_ampdu *tap)
 {
 	struct ieee80211com *ic = ni->ni_ic;
-	uint16_t args[4];
 	int tid, dialogtoken;
 	static int tokens = 0;	/* XXX */
+	union ieee80211_send_action_args vargs;
 
 	/* XXX locking */
 	if ((tap->txa_flags & IEEE80211_AGGR_SETUP) == 0) {
@@ -1793,14 +1795,15 @@ ieee80211_ampdu_request(struct ieee80211
 	tid = WME_AC_TO_TID(tap->txa_ac);
 	tap->txa_start = ni->ni_txseqs[tid];
 
-	args[0] = dialogtoken;
-	args[1]	= IEEE80211_BAPS_POLICY_IMMEDIATE
+	vargs.fixedarg[0] = dialogtoken;
+	vargs.fixedarg[1] = IEEE80211_BAPS_POLICY_IMMEDIATE
 		| SM(tid, IEEE80211_BAPS_TID)
 		| SM(IEEE80211_AGGR_BAWMAX, IEEE80211_BAPS_BUFSIZ)
 		;
-	args[2] = 0;	/* batimeout */
+	vargs.fixedarg[2] = 0;	/* batimeout */
 	/* NB: do first so there's no race against reply */
-	if (!ic->ic_addba_request(ni, tap, dialogtoken, args[1], args[2])) {
+	if (!ic->ic_addba_request(ni, tap, dialogtoken, vargs.fixedarg[1],
+	    vargs.fixedarg[2])) {
 		/* unable to setup state, don't make request */
 		IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_11N,
 		    ni, "%s: could not setup BA stream for AC %d",
@@ -1814,11 +1817,11 @@ ieee80211_ampdu_request(struct ieee80211
 	}
 	tokens = dialogtoken;			/* allocate token */
 	/* NB: after calling ic_addba_request so driver can set txa_start */
-	args[3] = SM(tap->txa_start, IEEE80211_BASEQ_START)
+	vargs.fixedarg[3] = SM(tap->txa_start, IEEE80211_BASEQ_START)
 		| SM(0, IEEE80211_BASEQ_FRAG)
 		;
 	return ic->ic_send_action(ni, IEEE80211_ACTION_CAT_BA,
-		IEEE80211_ACTION_BA_ADDBA_REQUEST, args);
+		IEEE80211_ACTION_BA_ADDBA_REQUEST, vargs);
 }
 
 /*
@@ -1831,7 +1834,7 @@ ieee80211_ampdu_stop(struct ieee80211_no
 {
 	struct ieee80211com *ic = ni->ni_ic;
 	struct ieee80211vap *vap = ni->ni_vap;
-	uint16_t args[4];
+	union ieee80211_send_action_args vargs;
 
 	/* XXX locking */
 	tap->txa_flags &= ~IEEE80211_AGGR_BARPEND;
@@ -1842,11 +1845,11 @@ ieee80211_ampdu_stop(struct ieee80211_no
 		vap->iv_stats.is_ampdu_stop++;
 
 		ic->ic_addba_stop(ni, tap);
-		args[0] = WME_AC_TO_TID(tap->txa_ac);
-		args[1] = IEEE80211_DELBAPS_INIT;
-		args[2] = reason;			/* XXX reason code */
+		vargs.fixedarg[0] = WME_AC_TO_TID(tap->txa_ac);
+		vargs.fixedarg[1] = IEEE80211_DELBAPS_INIT;
+		vargs.fixedarg[2] = reason;		/* XXX reason code */
 		ieee80211_send_action(ni, IEEE80211_ACTION_CAT_BA,
-			IEEE80211_ACTION_BA_DELBA, args);
+			IEEE80211_ACTION_BA_DELBA, vargs);
 	} else {
 		IEEE80211_NOTE(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_11N,
 		    ni, "%s: BA stream for AC %d not running (reason %d)",

Modified: projects/mesh11s/sys/net80211/ieee80211_mesh.c
==============================================================================
--- projects/mesh11s/sys/net80211/ieee80211_mesh.c	Thu May 14 16:56:56 2009	(r192110)
+++ projects/mesh11s/sys/net80211/ieee80211_mesh.c	Thu May 14 17:04:00 2009	(r192111)
@@ -89,13 +89,6 @@ static const int ieee80211_mesh_maxretri
 /* non static for sysctl hookup */
 int	ieee80211_mesh_ttl = 31;
 
-/* unalligned little endian access */     
-#define LE_READ_2(p)					\
-	((uint16_t)					\
-	 ((((const uint8_t *)(p))[0]      ) |		\
-	  (((const uint8_t *)(p))[1] <<  8)))
-
-
 static const char *nodemeshstates[] = {
 	"IDLE",
 	"OPEN SENT",
@@ -273,9 +266,14 @@ mesh_input(struct ieee80211_node *ni, st
 	case IEEE80211_FC0_TYPE_DATA:
 		IEEE80211_NOTE(vap, IEEE80211_MSG_MESH, ni,
 		    "%s", "received data frame");
-		/* XXX: make sure we already peered with this node */
+		if (ni->ni_peerstate != IEEE80211_NODE_MESH_ESTABLISHED) {
+			IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_MESH,
+			    ni->ni_macaddr, NULL,
+			    "peer link not yet established (%s)",
+			    nodemeshstates[ni->ni_peerstate]);
+		}	
 		hdrspace = ieee80211_hdrspace(ic, wh)
-		    + sizeof(struct ieee80211_meshcontrol);
+		    + sizeof(struct ieee80211_meshcntl);
 		if (m->m_len < hdrspace &&
 		    (m = m_pullup(m, hdrspace)) == NULL) {
 			IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_ANY,
@@ -489,7 +487,7 @@ mesh_recv_mgmt(struct ieee80211_node *ni
 		if ((scan.capinfo & (IEEE80211_CAPINFO_ESS|IEEE80211_CAPINFO_IBSS)) == 0 &&
 		    !IEEE80211_ADDR_EQ(wh->i_addr2, ni->ni_macaddr) &&
 		    IEEE80211_ADDR_EQ(wh->i_addr3, zerobssid)) {
-			uint16_t args[4];
+			union ieee80211_send_action_args vargs;
 			/*
 			 * Create a new entry in the neighbor table.
 			 */
@@ -507,10 +505,10 @@ mesh_recv_mgmt(struct ieee80211_node *ni
 			    IEEE80211_MSG_MESH,
 			    ni, "peer link: switching to state %s",
 			    nodemeshstates[ni->ni_peerstate]);
-			args[0] = ni->ni_plid;
+			vargs.fixedarg[0] = ni->ni_plid;
 			ieee80211_send_action(ni,
 			    IEEE80211_ACTION_CAT_MESHPEERING,
-			    IEEE80211_ACTION_MESHPEERING_OPEN, args);
+			    IEEE80211_ACTION_MESHPEERING_OPEN, vargs);
 			ni->ni_mrcount = 0;
 			mesh_peer_timeout_setup(ni);
 		}
@@ -631,8 +629,9 @@ mesh_recv_action(struct ieee80211_node *
 	struct ieee80211_meshid_ie *meshid;
 	struct ieee80211_meshconf_ie *meshconf;
 	struct ieee80211_meshpeer_ie *meshpeer;
+	struct ieee80211_meshpreq_ie *meshpreq;
 	uint8_t *frm, *efrm;
-	uint16_t args[4];
+	union ieee80211_send_action_args vargs;
 		
 	wh = mtod(m0, struct ieee80211_frame *);
 	ia = (struct ieee80211_action *) &wh[1];
@@ -652,6 +651,7 @@ mesh_recv_action(struct ieee80211_node *
 	meshid = NULL;
 	meshpeer = NULL;
 	meshconf = NULL;
+	meshpreq = NULL;
 	while (efrm - frm > 1) {
 		IEEE80211_VERIFY_LENGTH(efrm - frm, frm[1] + 2, return);
 		switch (*frm) {
@@ -663,32 +663,44 @@ mesh_recv_action(struct ieee80211_node *
 			break;
 		case IEEE80211_ELEMID_MESHPEER:
 			meshpeer = (struct ieee80211_meshpeer_ie *) frm;
-			meshpeer->peer_llinkid = LE_READ_2(&meshpeer->peer_llinkid);
-			meshpeer->peer_linkid = LE_READ_2(&meshpeer->peer_linkid);
-			meshpeer->peer_rcode = LE_READ_2(&meshpeer->peer_rcode);
+			meshpeer->peer_llinkid =
+			    LE_READ_2(&meshpeer->peer_llinkid);
+			meshpeer->peer_linkid =
+			    LE_READ_2(&meshpeer->peer_linkid);
+			meshpeer->peer_rcode =
+			    LE_READ_2(&meshpeer->peer_rcode);
+			break;
+		case IEEE80211_ELEMID_MESHPREQ:
+			meshpreq = (struct ieee80211_meshpreq_ie *) frm;
+			meshpreq->preq_id = LE_READ_4(&meshpreq->preq_id);
+			meshpreq->preq_origseq =
+			    LE_READ_4(&meshpreq->preq_origseq);
+			meshpreq->preq_lifetime =
+			    LE_READ_4(&meshpreq->preq_lifetime);
+			meshpreq->preq_metric =
+			    LE_READ_4(&meshpreq->preq_metric);
 			break;
 		}
 		frm += frm[1] + 2;
 	}
-	/*
-	 * Check if we agree on Mesh ID and Configuration.
-	 * XXX: TBD
-	 */
-	if (mesh_verify_meshid(vap, meshid) ||
-	    mesh_verify_meshconf(vap, meshconf) ||
-	    !meshpeer) {
-		IEEE80211_DISCARD(vap,
-		    IEEE80211_MSG_ACTION | IEEE80211_MSG_MESH,
-		    wh, NULL, "%s", "action frame not for our mesh");
-		vap->iv_stats.is_rx_mgtdiscard++;
-		return;
-	}
 
 	/*
 	 * Mesh Peer Link Management Finite State Machine handling.
 	 */
 	switch (ia->ia_category) {
 	case IEEE80211_ACTION_CAT_MESHPEERING:
+		/*
+		 * Check if we agree on the required fields.
+		 */
+		if (mesh_verify_meshid(vap, meshid) ||
+		    mesh_verify_meshconf(vap, meshconf) ||
+		    !meshpeer) {
+			IEEE80211_DISCARD(vap,
+			    IEEE80211_MSG_ACTION | IEEE80211_MSG_MESH,
+			    wh, NULL, "%s", "action frame not for our mesh");
+			vap->iv_stats.is_rx_mgtdiscard++;
+			return;
+		}
 		switch (ia->ia_action) {
 		case IEEE80211_ACTION_MESHPEERING_OPEN:
 			IEEE80211_NOTE(vap,
@@ -703,27 +715,29 @@ mesh_recv_action(struct ieee80211_node *
 				    nodemeshstates[ni->ni_peerstate]);
 				ni->ni_llid = meshpeer->peer_llinkid;
 				get_random_bytes(&ni->ni_plid, 2);
-				args[0] = ni->ni_plid;
+				vargs.fixedarg[0] = ni->ni_plid;
 				/* Announce we're open too... */
 				ieee80211_send_action(ni,
 				    IEEE80211_ACTION_CAT_MESHPEERING,
-				    IEEE80211_ACTION_MESHPEERING_OPEN, args);
+				    IEEE80211_ACTION_MESHPEERING_OPEN, vargs);
 				/* ...and confirm the link. */
-				args[0] = ni->ni_plid;
-				args[1] = ni->ni_llid;
+				vargs.fixedarg[0] = ni->ni_plid;
+				vargs.fixedarg[1] = ni->ni_llid;
 				ieee80211_send_action(ni,
 				    IEEE80211_ACTION_CAT_MESHPEERING,
-				    IEEE80211_ACTION_MESHPEERING_CONFIRM, args);
+				    IEEE80211_ACTION_MESHPEERING_CONFIRM,
+				    vargs);
 				mesh_peer_timeout_setup(ni);
 				break;
 			case IEEE80211_NODE_MESH_OPENRCV:
-				/* We received a duplicate open, confirm again. */
+				/* Duplicate open, confirm again. */
 				ni->ni_llid = meshpeer->peer_llinkid;
-				args[0] = ni->ni_plid;
-				args[1] = ni->ni_llid;
+				vargs.fixedarg[0] = ni->ni_plid;
+				vargs.fixedarg[1] = ni->ni_llid;
 				ieee80211_send_action(ni,
 				    IEEE80211_ACTION_CAT_MESHPEERING,
-				    IEEE80211_ACTION_MESHPEERING_CONFIRM, args);
+				    IEEE80211_ACTION_MESHPEERING_CONFIRM,
+				    vargs);
 				break;
 			case IEEE80211_NODE_MESH_OPENSNT:
 				ni->ni_peerstate = IEEE80211_NODE_MESH_OPENRCV;
@@ -732,41 +746,47 @@ mesh_recv_action(struct ieee80211_node *
 				    IEEE80211_MSG_MESH,
 				    ni, "peer link: switching to state %s",
 				    nodemeshstates[ni->ni_peerstate]);
-				args[0] = ni->ni_plid;
-				args[1] = ni->ni_llid;
+				vargs.fixedarg[0] = ni->ni_plid;
+				vargs.fixedarg[1] = ni->ni_llid;
 				ieee80211_send_action(ni,
 				    IEEE80211_ACTION_CAT_MESHPEERING,
-				    IEEE80211_ACTION_MESHPEERING_CONFIRM, args);
+				    IEEE80211_ACTION_MESHPEERING_CONFIRM,
+				    vargs);
 				/* NB: don't setup/clear any timeout */
 				break;
 			case IEEE80211_NODE_MESH_CONFIRMRECV:
-				ni->ni_peerstate = IEEE80211_NODE_MESH_ESTABLISHED;
+				ni->ni_peerstate =
+				    IEEE80211_NODE_MESH_ESTABLISHED;
 				IEEE80211_NOTE(vap,
 				    IEEE80211_MSG_MESH,
 				    ni, "peer link: switching to state %s",
 				    nodemeshstates[ni->ni_peerstate]);
 				ni->ni_llid = meshpeer->peer_llinkid;
-				args[0] = ni->ni_plid;
-				args[1] = ni->ni_llid;
+				vargs.fixedarg[0] = ni->ni_plid;
+				vargs.fixedarg[1] = ni->ni_llid;
 				ieee80211_send_action(ni,
 				    IEEE80211_ACTION_CAT_MESHPEERING,
-				    IEEE80211_ACTION_MESHPEERING_CONFIRM, args);
+				    IEEE80211_ACTION_MESHPEERING_CONFIRM,
+				    vargs);
 				mesh_peer_timeout_stop(ni);
 				break;
 			case IEEE80211_NODE_MESH_ESTABLISHED:
-				args[0] = ni->ni_plid;
-				args[1] = ni->ni_llid;
+				vargs.fixedarg[0] = ni->ni_plid;
+				vargs.fixedarg[1] = ni->ni_llid;
 				ieee80211_send_action(ni,
 				    IEEE80211_ACTION_CAT_MESHPEERING,
-				    IEEE80211_ACTION_MESHPEERING_CONFIRM, args);
+				    IEEE80211_ACTION_MESHPEERING_CONFIRM,
+				    vargs);
 				break;
 			case IEEE80211_NODE_MESH_HOLDING:
-				args[0] = ni->ni_llid;
-				args[1] = ni->ni_plid;
-				args[2] = IEEE80211_REASON_MESH_MAX_RETRIES;
+				vargs.fixedarg[0] = ni->ni_llid;
+				vargs.fixedarg[1] = ni->ni_plid;
+				vargs.fixedarg[2] =
+				    IEEE80211_REASON_MESH_MAX_RETRIES;
 				ieee80211_send_action(ni,
 				    IEEE80211_ACTION_CAT_MESHPEERING,
-				    IEEE80211_ACTION_MESHPEERING_CLOSE, args);
+				    IEEE80211_ACTION_MESHPEERING_CLOSE,
+				    vargs);
 				break;
 			}
 			break;
@@ -777,7 +797,8 @@ mesh_recv_action(struct ieee80211_node *
 			    meshpeer->peer_llinkid, meshpeer->peer_linkid);
 			switch (ni->ni_peerstate) {
 			case IEEE80211_NODE_MESH_OPENRCV:
-				ni->ni_peerstate = IEEE80211_NODE_MESH_ESTABLISHED;
+				ni->ni_peerstate =
+				    IEEE80211_NODE_MESH_ESTABLISHED;
 				IEEE80211_NOTE(vap,
 				    IEEE80211_MSG_MESH,
 				    ni, "peer link: switching to state %s",
@@ -785,19 +806,21 @@ mesh_recv_action(struct ieee80211_node *
 				mesh_peer_timeout_stop(ni);
 				break;
 			case IEEE80211_NODE_MESH_OPENSNT:
-				ni->ni_peerstate = IEEE80211_NODE_MESH_CONFIRMRECV;
+				ni->ni_peerstate =
+				    IEEE80211_NODE_MESH_CONFIRMRECV;
 				IEEE80211_NOTE(vap,
 				    IEEE80211_MSG_MESH,
 				    ni, "peer link: switching to state %s",
 				    nodemeshstates[ni->ni_peerstate]);
 				break;
 			case IEEE80211_NODE_MESH_HOLDING:
-				args[0] = ni->ni_llid;
-				args[1] = ni->ni_plid;
-				args[2] = IEEE80211_REASON_MESH_MAX_RETRIES;
+				vargs.fixedarg[0] = ni->ni_llid;
+				vargs.fixedarg[1] = ni->ni_plid;
+				vargs.fixedarg[2] = IEEE80211_REASON_MESH_MAX_RETRIES;
 				ieee80211_send_action(ni,
 				    IEEE80211_ACTION_CAT_MESHPEERING,
-				    IEEE80211_ACTION_MESHPEERING_CLOSE, args);
+				    IEEE80211_ACTION_MESHPEERING_CLOSE,
+				    vargs);
 				break;
 			default:
 				IEEE80211_DISCARD(vap,
@@ -824,8 +847,49 @@ mesh_recv_action(struct ieee80211_node *
 			break;
 		}
 		break;
+	case IEEE80211_ACTION_CAT_MESHPATH:
+		switch (ia->ia_action) {
+		case IEEE80211_ACTION_MESHPATH_REQ:
+			if (meshpreq == NULL) {
+				IEEE80211_DISCARD(vap,
+				    IEEE80211_MSG_ACTION | IEEE80211_MSG_MESH,
+				    wh, NULL, "%s", "preq without IE");
+				vap->iv_stats.is_rx_mgtdiscard++;
+				return;
+			}
+			/*
+			 * Is the peer trying to find us?
+			 */
+			if (IEEE80211_ADDR_EQ(vap->iv_myaddr,
+			    meshpreq->preq_targets[0].target_addr)) {
+				struct ieee80211_meshprep_ie prep;
+				/*
+				 * Build and send a path reply frame.
+				 */
+				prep.prep_flags = 0;
+				prep.prep_hopcount = 0;
+				prep.prep_ttl = ieee80211_mesh_ttl;
+				IEEE80211_ADDR_COPY(prep.prep_targetaddr,
+				    meshpreq->preq_targets[0].target_addr);
+				prep.prep_targetseq = meshpreq->preq_origseq;
+				prep.prep_lifetime = 5000;
+				prep.prep_metric = 0;
+				IEEE80211_ADDR_COPY(prep.prep_origaddr,
+				    vap->iv_myaddr);
+				prep.prep_origseq = 1;
+
+				vargs.ptrarg = &prep;
+				ieee80211_send_action(ni,
+				    IEEE80211_ACTION_CAT_MESHPATH,
+				    IEEE80211_ACTION_MESHPATH_REP,
+				    vargs);
+			}
+			break;
+		}
+		break;
 	default:
-		IEEE80211_DISCARD(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_MESH,
+		IEEE80211_DISCARD(vap,
+		    IEEE80211_MSG_ACTION | IEEE80211_MSG_MESH,
 		    wh, NULL, "%s", "not handled");
 		vap->iv_stats.is_rx_mgtdiscard++;
 	}
@@ -876,7 +940,7 @@ mesh_peer_timeout_cb(void *arg)
 {
 	struct ieee80211_node *ni = (struct ieee80211_node *)arg;
 	struct ieee80211vap *vap = ni->ni_vap;
-	uint16_t args[4];
+	union ieee80211_send_action_args vargs;
 
 	IEEE80211_NOTE(vap,
 	    IEEE80211_MSG_MESH,
@@ -887,11 +951,11 @@ mesh_peer_timeout_cb(void *arg)
 	case IEEE80211_NODE_MESH_OPENSNT:
 	case IEEE80211_NODE_MESH_OPENRCV:
 		if (ni->ni_mrcount == ieee80211_mesh_maxretries) {
-			args[0] = ni->ni_plid;
-			args[2] = IEEE80211_REASON_MESH_MAX_RETRIES;
+			vargs.fixedarg[0] = ni->ni_plid;
+			vargs.fixedarg[2] = IEEE80211_REASON_MESH_MAX_RETRIES;
 			ieee80211_send_action(ni,
 			    IEEE80211_ACTION_CAT_MESHPEERING,
-			    IEEE80211_ACTION_MESHPEERING_CLOSE, args);
+			    IEEE80211_ACTION_MESHPEERING_CLOSE, vargs);
 			ni->ni_mrcount = 0;
 			ni->ni_peerstate = IEEE80211_NODE_MESH_HOLDING;
 			IEEE80211_NOTE(vap,
@@ -900,21 +964,22 @@ mesh_peer_timeout_cb(void *arg)
 			    nodemeshstates[ni->ni_peerstate]);
 			mesh_peer_timeout_setup(ni);
 		} else {
-			args[0] = ni->ni_plid;
+			vargs.fixedarg[0] = ni->ni_plid;
 			ieee80211_send_action(ni,
 			    IEEE80211_ACTION_CAT_MESHPEERING,
-			    IEEE80211_ACTION_MESHPEERING_OPEN, args);
+			    IEEE80211_ACTION_MESHPEERING_OPEN, vargs);
 			ni->ni_mrcount++;
 			mesh_peer_timeout_backoff(ni);
 		}
 		break;
 	case IEEE80211_NODE_MESH_CONFIRMRECV:
 		if (ni->ni_mrcount == ieee80211_mesh_maxretries) {
-			args[0] = ni->ni_plid;
-			args[2] = IEEE80211_REASON_MESH_CONFIRM_TIMEOUT;
+			vargs.fixedarg[0] = ni->ni_plid;
+			vargs.fixedarg[2] =
+			    IEEE80211_REASON_MESH_CONFIRM_TIMEOUT;
 			ieee80211_send_action(ni,
 			    IEEE80211_ACTION_CAT_MESHPEERING,
-			    IEEE80211_ACTION_MESHPEERING_CLOSE, args);
+			    IEEE80211_ACTION_MESHPEERING_CLOSE, vargs);
 			ni->ni_mrcount = 0;
 			ni->ni_peerstate = IEEE80211_NODE_MESH_HOLDING;
 			IEEE80211_NOTE(vap,

Modified: projects/mesh11s/sys/net80211/ieee80211_mesh.h
==============================================================================
--- projects/mesh11s/sys/net80211/ieee80211_mesh.h	Thu May 14 16:56:56 2009	(r192110)
+++ projects/mesh11s/sys/net80211/ieee80211_mesh.h	Thu May 14 17:04:00 2009	(r192111)
@@ -215,7 +215,7 @@ struct ieee80211_meshpreq_ie {
 	uint8_t		preq_flags;
 	uint8_t		preq_hopcount;
 	uint8_t		preq_ttl;
-	uint8_t		preq_id;
+	uint32_t	preq_id;
 	uint8_t		preq_origaddr[IEEE80211_ADDR_LEN];
 	uint32_t	preq_origseq;	/* HWMP Sequence Number */
 	/* NB: may have Originator Proxied Address */
@@ -226,7 +226,7 @@ struct ieee80211_meshpreq_ie {
 		uint8_t		target_flags;
 		uint8_t		target_addr[IEEE80211_ADDR_LEN];
 		uint32_t	target_seq;	/* HWMP Sequence Number */
-	} targets[1] __packed;	/* NB: variable size */
+	} preq_targets[1] __packed;	/* NB: variable size */
 } __packed;
 
 /* Mesh Path Reply */
@@ -254,7 +254,7 @@ struct ieee80211_meshperr_ie {
 	struct {
 		uint8_t		dest_addr[IEEE80211_ADDR_LEN];
 		uint32_t	dest_seq;	/* HWMP Sequence Number */
-	} dests[1] __packed;		/* NB: variable size */
+	} perr_dests[1] __packed;		/* NB: variable size */
 } __packed;
 
 /* Mesh Proxy Update */
@@ -278,18 +278,30 @@ struct ieee80211_meshpuc_ie {
  */
 #define	IEEE80211_ACTION_CAT_MESHPEERING	30	/* XXX Linux */
 #define	IEEE80211_ACTION_CAT_MESHLINK		13
-#define	IEEE80211_ACTION_CAT_PATHSEL		14
+#define	IEEE80211_ACTION_CAT_MESHPATH		32	/* XXX Linux */
 #define	IEEE80211_ACTION_CAT_INTERWORK		15
 #define	IEEE80211_ACTION_CAT_RESOURCE		16
 #define	IEEE80211_ACTION_CAT_PROXY		17
 
+/*
+ * Mesh Peering Action codes.
+ */
 enum {
 	IEEE80211_ACTION_MESHPEERING_OPEN	= 0,
 	IEEE80211_ACTION_MESHPEERING_CONFIRM	= 1,
 	IEEE80211_ACTION_MESHPEERING_CLOSE	= 2,
 };
 
-struct ieee80211_meshcontrol {
+/*
+ * Mesh Path Selection Action codes.
+ */
+enum {
+	IEEE80211_ACTION_MESHPATH_REQ	= 0,
+	IEEE80211_ACTION_MESHPATH_REP	= 1,
+	IEEE80211_ACTION_MESHPATH_ERR	= 2,
+};
+
+struct ieee80211_meshcntl {
 	uint8_t		mc_flags;
 	uint8_t		mc_ttl;
 	uint32_t	mc_seq;

Modified: projects/mesh11s/sys/net80211/ieee80211_output.c
==============================================================================
--- projects/mesh11s/sys/net80211/ieee80211_output.c	Thu May 14 16:56:56 2009	(r192110)
+++ projects/mesh11s/sys/net80211/ieee80211_output.c	Thu May 14 17:04:00 2009	(r192111)
@@ -538,7 +538,7 @@ ieee80211_send_setup(
  */
 int
 ieee80211_send_action(struct ieee80211_node *ni,
-	int category, int action, uint16_t args[4])
+	int category, int action, union ieee80211_send_action_args vargs)
 {
 #define	senderr(_x, _v)	do { vap->iv_stats._v++; ret = _x; goto bad; } while (0)
 #define	ADDSHORT(frm, v) do {			\
@@ -555,7 +555,7 @@ ieee80211_send_action(struct ieee80211_n
 	struct mbuf *m;
 	uint8_t *frm;
 	uint16_t baparamset;
-	int ret, addsize;
+	int ret, addsize = 0;
 
 	KASSERT(ni != NULL, ("null node"));
 
@@ -571,19 +571,32 @@ ieee80211_send_action(struct ieee80211_n
 		ieee80211_node_refcnt(ni)+1);
 	ieee80211_ref_node(ni);
 
-	addsize = 0;
 	switch (category) {
 	case IEEE80211_ACTION_CAT_BA:
 	case IEEE80211_ACTION_CAT_HT:
-		addsize += sizeof(struct ieee80211_action_ba_addbaresponse);
+		addsize = sizeof(struct ieee80211_action_ba_addbaresponse);
 		break;
 	case IEEE80211_ACTION_CAT_MESHPEERING:
-		addsize += sizeof(uint16_t);		/* capabilities */
-		addsize += 2 + IEEE80211_RATE_SIZE;
-		addsize += 2 + (IEEE80211_RATE_MAXSIZE - IEEE80211_RATE_SIZE);
-		addsize += 2 + vap->iv_meshidlen;	/* Mesh ID */
-		addsize += sizeof(struct ieee80211_meshconf_ie);
-		addsize += sizeof(struct ieee80211_meshpeer_ie);
+		addsize = sizeof(uint16_t)		/* capabilities */
+			+ 2 + IEEE80211_RATE_SIZE
+			+ 2 + (IEEE80211_RATE_MAXSIZE - IEEE80211_RATE_SIZE)
+			+ 2 + vap->iv_meshidlen		/* Mesh ID */
+			+ sizeof(struct ieee80211_meshconf_ie)
+			+ sizeof(struct ieee80211_meshpeer_ie);
+		break;
+	case IEEE80211_ACTION_CAT_MESHPATH:
+		switch (action) {
+		case IEEE80211_ACTION_MESHPATH_REQ:
+			/* XXX more than one destination */
+			addsize = sizeof(struct ieee80211_meshpreq_ie);
+			break;
+		case IEEE80211_ACTION_MESHPATH_REP:
+			addsize = sizeof(struct ieee80211_meshprep_ie);
+			break;
+		case IEEE80211_ACTION_MESHPATH_ERR:
+			addsize = sizeof(struct ieee80211_meshperr_ie);
+			break;
+		}
 		break;
 	}
 	m = ieee80211_getmgtframe(&frm,
@@ -606,39 +619,43 @@ ieee80211_send_action(struct ieee80211_n
 			    IEEE80211_MSG_ACTION | IEEE80211_MSG_11N, ni,
 			    "send ADDBA request: dialogtoken %d "
 			    "baparamset 0x%x (tid %d) batimeout 0x%x baseqctl 0x%x",
-			    args[0], args[1], MS(args[1], IEEE80211_BAPS_TID),
-			    args[2], args[3]);
-
-			*frm++ = args[0];	/* dialog token */
-			ADDSHORT(frm, args[1]);	/* baparamset */
-			ADDSHORT(frm, args[2]);	/* batimeout */
-			ADDSHORT(frm, args[3]);	/* baseqctl */
+			    vargs.fixedarg[0], vargs.fixedarg[1],
+			    MS(vargs.fixedarg[1], IEEE80211_BAPS_TID),
+			    vargs.fixedarg[2], vargs.fixedarg[3]);
+
+			*frm++ = vargs.fixedarg[0];	/* dialog token */
+			ADDSHORT(frm, vargs.fixedarg[1]);	/* baparamset */
+			ADDSHORT(frm, vargs.fixedarg[2]);	/* batimeout */
+			ADDSHORT(frm, vargs.fixedarg[3]);	/* baseqctl */
 			break;
 		case IEEE80211_ACTION_BA_ADDBA_RESPONSE:
 			IEEE80211_NOTE(vap,
 			    IEEE80211_MSG_ACTION | IEEE80211_MSG_11N, ni,
 			    "send ADDBA response: dialogtoken %d status %d "
 			    "baparamset 0x%x (tid %d) batimeout %d",
-			    args[0], args[1], args[2],
-			    MS(args[2], IEEE80211_BAPS_TID), args[3]);
-
-			*frm++ = args[0];	/* dialog token */
-			ADDSHORT(frm, args[1]);	/* statuscode */
-			ADDSHORT(frm, args[2]);	/* baparamset */
-			ADDSHORT(frm, args[3]);	/* batimeout */
+			    vargs.fixedarg[0], vargs.fixedarg[1],
+			    vargs.fixedarg[2], MS(vargs.fixedarg[2],
+			    IEEE80211_BAPS_TID), vargs.fixedarg[3]);
+
+			*frm++ = vargs.fixedarg[0];	/* dialog token */
+			ADDSHORT(frm, vargs.fixedarg[1]);	/* statuscode */
+			ADDSHORT(frm, vargs.fixedarg[2]);	/* baparamset */
+			ADDSHORT(frm, vargs.fixedarg[3]);	/* batimeout */
 			break;
 		case IEEE80211_ACTION_BA_DELBA:
 			/* XXX */
-			baparamset = SM(args[0], IEEE80211_DELBAPS_TID)
-				   | args[1]
+			baparamset = SM(vargs.fixedarg[0],
+				     IEEE80211_DELBAPS_TID)
+				   | vargs.fixedarg[1]
 				   ;
 			ADDSHORT(frm, baparamset);
-			ADDSHORT(frm, args[2]);	/* reason code */
+			ADDSHORT(frm, vargs.fixedarg[2]);  /* reason code */
 
 			IEEE80211_NOTE(vap,
 			    IEEE80211_MSG_ACTION | IEEE80211_MSG_11N, ni,
 			    "send DELBA action: tid %d, initiator %d reason %d",
-			    args[0], args[1], args[2]);
+			    vargs.fixedarg[0], vargs.fixedarg[1],
+			    vargs.fixedarg[2]);
 			break;
 		default:
 			goto badaction;
@@ -677,14 +694,16 @@ ieee80211_send_action(struct ieee80211_n
 		case IEEE80211_ACTION_MESHPEERING_OPEN:
 			IEEE80211_NOTE(vap,
 			    IEEE80211_MSG_ACTION | IEEE80211_MSG_MESH, ni,
-			    "send PEER OPEN action: localid 0x%x", args[0]);
+			    "send PEER OPEN action: localid 0x%x",
+			    vargs.fixedarg[0]);
 			ADDSHORT(frm, getcapinfo(vap, ni->ni_chan));
 			frm = ieee80211_add_rates(frm, rs);
 			frm = ieee80211_add_xrates(frm, rs);
 			frm = ieee80211_add_meshid(frm, vap);
 			frm = ieee80211_add_meshconf(frm, vap);
 			frm = ieee80211_add_meshpeer(frm,
-			    IEEE80211_MESH_PEER_LINK_OPEN, args[0], 0, 0);
+			    IEEE80211_MESH_PEER_LINK_OPEN,
+			    vargs.fixedarg[0], 0, 0);
 			break;
 		/*
 		 * mesh peer confirm action frame format:
@@ -703,7 +722,8 @@ ieee80211_send_action(struct ieee80211_n
 			IEEE80211_NOTE(vap,
 			    IEEE80211_MSG_ACTION | IEEE80211_MSG_MESH, ni,
 			    "send PEER CONFIRM action: localid 0x%x, "
-			    "peerid 0x%x", args[0], args[1]);
+			    "peerid 0x%x", vargs.fixedarg[0],
+			    vargs.fixedarg[1]);
 			ADDSHORT(frm, getcapinfo(vap, ni->ni_chan));
 			ADDSHORT(frm, 0);	/* status code */
 			ADDSHORT(frm, 0);	/* AID */
@@ -712,7 +732,8 @@ ieee80211_send_action(struct ieee80211_n
 			frm = ieee80211_add_meshid(frm, vap);
 			frm = ieee80211_add_meshconf(frm, vap);
 			frm = ieee80211_add_meshpeer(frm,
-			    IEEE80211_MESH_PEER_LINK_CONFIRM, args[0], args[1],
+			    IEEE80211_MESH_PEER_LINK_CONFIRM,
+			    vargs.fixedarg[0], vargs.fixedarg[1],
 			    0);
 			break;
 		/*
@@ -727,15 +748,43 @@ ieee80211_send_action(struct ieee80211_n
 			IEEE80211_NOTE(vap,
 			    IEEE80211_MSG_ACTION | IEEE80211_MSG_MESH, ni,
 			    "sending PEER CLOSE action: localid 0x%x, "
-			    "peerid 0x%x reason %d", args[0], args[1], args[2]);
-			ADDSHORT(frm, args[2]);		/* reason code */
+			    "peerid 0x%x reason %d", vargs.fixedarg[0],
+			    vargs.fixedarg[1], vargs.fixedarg[2]);
+			ADDSHORT(frm, vargs.fixedarg[2]);   /* reason code */
 			frm = ieee80211_add_meshid(frm, vap);
 			frm = ieee80211_add_meshpeer(frm,
-			    IEEE80211_MESH_PEER_LINK_CLOSE, args[0], args[1],
-			    args[2]);
+			    IEEE80211_MESH_PEER_LINK_CLOSE,
+			    vargs.fixedarg[0], vargs.fixedarg[1],
+			    vargs.fixedarg[2]);
 			break;
 		}
 		break;
+	case IEEE80211_ACTION_CAT_MESHPATH:
+		switch (action) {
+		/*
+		 * mesh path request action frame format:
+		 *   [1] action
+		 *   [1] category
+		 *   [tlv] mesh preq
+		 */
+		case IEEE80211_ACTION_MESHPATH_REQ:
+			break;
+		/*
+		 * mesh path request action frame format:
+		 *   [1] action
+		 *   [1] category
+		 *   [tlv] mesh preq
+		 */
+		case IEEE80211_ACTION_MESHPATH_REP:
+			IEEE80211_NOTE(vap,
+			    IEEE80211_MSG_ACTION | IEEE80211_MSG_MESH, ni,
+			    "send PATH REPLY action: flags 0x%x, "
+			    "hopcount 0x%x", vargs.fixedarg[0],
+			    vargs.fixedarg[1]);
+				
+			break;	
+		}
+		break;
 	default:
 	badaction:
 		IEEE80211_NOTE(vap,
@@ -1237,7 +1286,7 @@ ieee80211_encap(struct ieee80211vap *vap
 	 * All Mesh data frames have a Mesh Control field.
 	 */
 	if (vap->iv_opmode == IEEE80211_M_MBSS)
-		hdrsize += sizeof(struct ieee80211_meshcontrol);
+		hdrsize += sizeof(struct ieee80211_meshcntl);
 	/*
 	 * Honor driver DATAPAD requirement.
 	 */

Modified: projects/mesh11s/sys/net80211/ieee80211_proto.h
==============================================================================
--- projects/mesh11s/sys/net80211/ieee80211_proto.h	Thu May 14 16:56:56 2009	(r192110)
+++ projects/mesh11s/sys/net80211/ieee80211_proto.h	Thu May 14 17:04:00 2009	(r192111)
@@ -65,7 +65,12 @@ void	ieee80211_syncflag_ext(struct ieee8
 int	ieee80211_input_all(struct ieee80211com *, struct mbuf *,
 		int, int, uint32_t);
 struct ieee80211_bpf_params;
-int	ieee80211_send_action(struct ieee80211_node *, int, int, uint16_t [4]);
+union ieee80211_send_action_args {
+	uint16_t	fixedarg[4];
+	void *		ptrarg;
+};
+int	ieee80211_send_action(struct ieee80211_node *, int, int,
+		union ieee80211_send_action_args);
 int	ieee80211_mgmt_output(struct ieee80211_node *, struct mbuf *, int,
 		struct ieee80211_bpf_params *);
 int	ieee80211_raw_xmit(struct ieee80211_node *, struct mbuf *,

Modified: projects/mesh11s/sys/net80211/ieee80211_var.h
==============================================================================
--- projects/mesh11s/sys/net80211/ieee80211_var.h	Thu May 14 16:56:56 2009	(r192110)
+++ projects/mesh11s/sys/net80211/ieee80211_var.h	Thu May 14 17:04:00 2009	(r192111)
@@ -276,7 +276,7 @@ struct ieee80211com {
 				    const uint8_t *frm, const uint8_t *efrm);
 	int			(*ic_send_action)(struct ieee80211_node *,
 				    int category, int action,
-				    uint16_t args[4]);
+				    union ieee80211_send_action_args);
 	/* check if A-MPDU should be enabled this station+ac */
 	int			(*ic_ampdu_enable)(struct ieee80211_node *,
 				    struct ieee80211_tx_ampdu *);


More information about the svn-src-projects mailing list