Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 8 Jun 2009 11:39:04 +0000 (UTC)
From:      Rui Paulo <rpaulo@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r193709 - projects/mesh11s/sys/net80211
Message-ID:  <200906081139.n58Bd42D028270@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: rpaulo
Date: Mon Jun  8 11:39:04 2009
New Revision: 193709
URL: http://svn.freebsd.org/changeset/base/193709

Log:
  Rework the encap logic to comply with F_DATAPAD issues.
  
  Idea from:	sam
  Sponsored by:	The FreeBSD Foundation

Modified:
  projects/mesh11s/sys/net80211/ieee80211_mesh.c
  projects/mesh11s/sys/net80211/ieee80211_output.c

Modified: projects/mesh11s/sys/net80211/ieee80211_mesh.c
==============================================================================
--- projects/mesh11s/sys/net80211/ieee80211_mesh.c	Mon Jun  8 11:24:23 2009	(r193708)
+++ projects/mesh11s/sys/net80211/ieee80211_mesh.c	Mon Jun  8 11:39:04 2009	(r193709)
@@ -232,7 +232,8 @@ mesh_input(struct ieee80211_node *ni, st
 	struct ieee80211com *ic = ni->ni_ic;
 	struct ifnet *ifp = vap->iv_ifp;
 	struct ieee80211_frame *wh;
-	int hdrlen, need_tap;
+	const struct ieee80211_meshcntl *mc;
+	int hdrspace, need_tap;
 	uint8_t dir, type, subtype, qos;
 
 	KASSERT(ni != NULL, ("null node"));
@@ -289,18 +290,27 @@ mesh_input(struct ieee80211_node *ni, st
 			vap->iv_stats.is_rx_wrongdir++;
 			goto err;
 		}
-		/* NB: not ieee80211_hdrspace, datapad is not honored */
-		hdrlen = ieee80211_hdrsize(wh)
-		    + sizeof(struct ieee80211_meshcntl);
-		if (m->m_len < hdrlen &&
-		    (m = m_pullup(m, hdrlen)) == NULL) {
+		/* pull up enough to get to the mesh control */
+		hdrspace = ieee80211_hdrspace(ic, wh);
+		if (m->m_len < hdrspace + sizeof(struct ieee80211_meshcntl) &&
+		    (m = m_pullup(m, hdrspace +
+		        sizeof(struct ieee80211_meshcntl) )) == NULL) {
 			IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_ANY,
 			    ni->ni_macaddr, NULL,
-			    "data too short: expecting %u", hdrlen);
+			    "data too short: expecting %u", hdrspace);
 			vap->iv_stats.is_rx_tooshort++;
 			goto out;		/* XXX */
 		}
 		/*
+		 * Now calculate the full extent of the headers. Note
+		 * ieee80211_decap will pull up anything we didn't get
+		 * above when it strips the 802.11 headers.
+		 */
+		mc = (const struct ieee80211_meshcntl *)
+		    (mtod(m, const uint8_t *) + hdrspace);
+		hdrspace += sizeof(struct ieee80211_meshcntl) +
+		    (mc->mc_flags & 3) * IEEE80211_ADDR_LEN;
+		/*
 		 * Save QoS bits for use below--before we strip the header.
 		 */
 		if (subtype == IEEE80211_FC0_SUBTYPE_QOS) {
@@ -313,7 +323,7 @@ mesh_input(struct ieee80211_node *ni, st
 		 * Next up, any fragmentation.
 		 */
 		if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
-			m = ieee80211_defrag(ni, m, hdrlen);
+			m = ieee80211_defrag(ni, m, hdrspace);
 			if (m == NULL) {
 				/* Fragment dropped or frame not complete yet */
 				goto out;
@@ -326,7 +336,7 @@ mesh_input(struct ieee80211_node *ni, st
 		/*
 		 * Finally, strip the 802.11 header.
 		 */
-		m = ieee80211_decap(vap, m, hdrlen);
+		m = ieee80211_decap(vap, m, hdrspace);
 		if (m == NULL) {
 			/* XXX mask bit to check for both */
 			/* don't count Null data frames as errors */

Modified: projects/mesh11s/sys/net80211/ieee80211_output.c
==============================================================================
--- projects/mesh11s/sys/net80211/ieee80211_output.c	Mon Jun  8 11:24:23 2009	(r193708)
+++ projects/mesh11s/sys/net80211/ieee80211_output.c	Mon Jun  8 11:39:04 2009	(r193709)
@@ -1220,6 +1220,9 @@ ieee80211_encap(struct ieee80211vap *vap
 	struct llc *llc;
 	int hdrsize, hdrspace, datalen, addqos, txfrag, is4addr;
 	ieee80211_seq seqno;
+	int meshhdrsize, meshae;
+	struct ieee80211_meshcntl_ae11 *mc;
+	uint32_t seq;
 
 	/*
 	 * Copy existing Ethernet header to a safe place.  The
@@ -1272,43 +1275,65 @@ ieee80211_encap(struct ieee80211vap *vap
 		hdrsize = sizeof(struct ieee80211_qosframe);
 	else
 		hdrsize = sizeof(struct ieee80211_frame);
-	/*
-	 * 4-address frames need to be generated for:
-	 * o packets sent through a WDS vap (IEEE80211_M_WDS)
-	 * o packets sent through a Mesh vap (IEEE80211_M_MBSS)
-	 * o packets sent through a vap marked for relaying
-	 *   (e.g. a station operating with dynamic WDS)
-	 */
-	is4addr = vap->iv_opmode == IEEE80211_M_WDS ||
-	    vap->iv_opmode == IEEE80211_M_MBSS ||
-	    ((vap->iv_flags_ext & IEEE80211_FEXT_4ADDR) &&
-	     !IEEE80211_ADDR_EQ(eh.ether_shost, vap->iv_myaddr));
-	if (is4addr)
-		hdrsize += IEEE80211_ADDR_LEN;
 	if (vap->iv_opmode == IEEE80211_M_MBSS) {
 		/*
-		 * Mesh data frames have a Mesh Control field.
-		 * XXX also cannot honor DATAPAD as this is used by
-		 * hardware and that hardware does not (yet) understand
-		 * 11s headers so will be confused.
+		 * Mesh data frames are encapsulated according to the
+		 * rules of Section 11B.8.5 (p.139 of D3.0 spec).
+		 * o Group Addressed data (aka multicast) originating
+		 *   at the local sta are sent w/ 3-address format and
+		 *   address extension mode 00
+		 * o Individually Addressed data (aka unicast) originating
+		 *   at the local sta are sent w/ 4-address format and
+		 *   address extension mode 00
+		 * o Group Addressed data forwarded from a non-mesh sta are
+		 *   sent w/ 3-address format and address extension mode 01
+		 * o Individually Address data from another sta are sent
+		 *   w/ 4-address format and address extension mode 10
 		 */
-		hdrsize += sizeof(struct ieee80211_meshcntl);
-		hdrspace = hdrsize;
+		is4addr = 0;		/* NB: don't use, disable */
+		meshhdrsize = sizeof(struct ieee80211_meshcntl);
+		/* XXX defines for AE modes */
+		/* XXX not right, need to check if from non-mesh-sta */
+		if (IEEE80211_ADDR_EQ(eh.ether_shost, vap->iv_myaddr)) {
+			if (!IEEE80211_IS_MULTICAST(eh.ether_dhost)) {
+				hdrsize += IEEE80211_ADDR_LEN;
+				meshae = 0;
+			} else
+				meshae = 4;		/* NB: pseudo */
+		} else if (IEEE80211_IS_MULTICAST(eh.ether_dhost)) {
+			meshae = 1;
+			meshhdrsize += 2*IEEE80211_ADDR_LEN;
+		} else {
+			meshae = 2;
+			meshhdrsize += 3*IEEE80211_ADDR_LEN;
+		}
 	} else {
 		/*
-		 * Honor driver DATAPAD requirement.
+		 * 4-address frames need to be generated for:
+		 * o packets sent through a WDS vap (IEEE80211_M_WDS)
+		 * o packets sent through a vap marked for relaying
+		 *   (e.g. a station operating with dynamic WDS)
 		 */
-		if (ic->ic_flags & IEEE80211_F_DATAPAD)
-			hdrspace = roundup(hdrsize, sizeof(uint32_t));
-		else
-			hdrspace = hdrsize;
+		is4addr = vap->iv_opmode == IEEE80211_M_WDS ||
+		    ((vap->iv_flags_ext & IEEE80211_FEXT_4ADDR) &&
+		     !IEEE80211_ADDR_EQ(eh.ether_shost, vap->iv_myaddr));
+		if (is4addr)
+			hdrsize += IEEE80211_ADDR_LEN;
+		meshhdrsize = meshae = 0;
 	}
+	/*
+	 * Honor driver DATAPAD requirement.
+	 */
+	if (ic->ic_flags & IEEE80211_F_DATAPAD)
+		hdrspace = roundup(hdrsize, sizeof(uint32_t));
+	else
+		hdrspace = hdrsize;
 
 	if (__predict_true((m->m_flags & M_FF) == 0)) {
 		/*
 		 * Normal frame.
 		 */
-		m = ieee80211_mbuf_adjust(vap, hdrspace, key, m);
+		m = ieee80211_mbuf_adjust(vap, hdrspace + meshhdrsize, key, m);
 		if (m == NULL) {
 			/* NB: ieee80211_mbuf_adjust handles msgs+statistics */
 			goto bad;
@@ -1327,14 +1352,14 @@ ieee80211_encap(struct ieee80211vap *vap
 		/*
 		 * Aggregated frame.
 		 */
-		m = ieee80211_ff_encap(vap, m, hdrspace, key);
+		m = ieee80211_ff_encap(vap, m, hdrspace + meshhdrsize, key);
 		if (m == NULL)
 #endif
 			goto bad;
 	}
 	datalen = m->m_pkthdr.len;		/* NB: w/o 802.11 header */
 
-	M_PREPEND(m, hdrspace, M_DONTWAIT);
+	M_PREPEND(m, hdrspace + meshhdrsize, M_DONTWAIT);
 	if (m == NULL) {
 		vap->iv_stats.is_tx_nobuf++;
 		goto bad;
@@ -1373,11 +1398,55 @@ ieee80211_encap(struct ieee80211vap *vap
 		IEEE80211_ADDR_COPY(wh->i_addr3, eh.ether_shost);
 		break;
 	case IEEE80211_M_MBSS:
-		wh->i_fc[1] = IEEE80211_FC1_DIR_DSTODS;
-		IEEE80211_ADDR_COPY(wh->i_addr1, ni->ni_macaddr);
-		IEEE80211_ADDR_COPY(wh->i_addr2, vap->iv_myaddr);
-		IEEE80211_ADDR_COPY(wh->i_addr3, eh.ether_dhost);
-		IEEE80211_ADDR_COPY(WH4(wh)->i_addr4, eh.ether_shost);
+		/* NB: offset by hdrspace to deal with DATAPAD */
+		mc = (struct ieee80211_meshcntl_ae11 *)
+		     (mtod(m, uint8_t *) + hdrspace);
+		switch (meshae) {
+		case 0:			/* ucast, no proxy */
+			wh->i_fc[1] = IEEE80211_FC1_DIR_DSTODS;
+			IEEE80211_ADDR_COPY(wh->i_addr1, ni->ni_macaddr);
+			IEEE80211_ADDR_COPY(wh->i_addr2, vap->iv_myaddr);
+			IEEE80211_ADDR_COPY(wh->i_addr3, eh.ether_dhost);
+			IEEE80211_ADDR_COPY(WH4(wh)->i_addr4, eh.ether_shost);
+			mc->mc_flags = 0;
+			break;
+		case 4:			/* mcast, no proxy */
+			wh->i_fc[1] = IEEE80211_FC1_DIR_FROMDS;
+			IEEE80211_ADDR_COPY(wh->i_addr1, eh.ether_dhost);
+			IEEE80211_ADDR_COPY(wh->i_addr2, vap->iv_myaddr);
+			IEEE80211_ADDR_COPY(wh->i_addr3, eh.ether_shost);
+			mc->mc_flags = 0;		/* NB: AE is really 0 */
+			break;
+		case 1:			/* mcast, proxy */
+			wh->i_fc[1] = IEEE80211_FC1_DIR_FROMDS;
+			IEEE80211_ADDR_COPY(wh->i_addr1, eh.ether_dhost);
+			IEEE80211_ADDR_COPY(wh->i_addr2, vap->iv_myaddr);
+			/* XXX not right, need MeshSA */
+			IEEE80211_ADDR_COPY(wh->i_addr3, eh.ether_shost);
+			mc->mc_flags = 1;
+			IEEE80211_ADDR_COPY(mc->mc_addr4, eh.ether_shost);
+			break;
+		case 2:			/* ucast, proxy */
+			wh->i_fc[1] = IEEE80211_FC1_DIR_DSTODS;
+			IEEE80211_ADDR_COPY(wh->i_addr1, ni->ni_macaddr);
+			IEEE80211_ADDR_COPY(wh->i_addr2, vap->iv_myaddr);
+			/* XXX not right, need MeshDA+MeshSA */
+			IEEE80211_ADDR_COPY(wh->i_addr3, eh.ether_dhost);
+			IEEE80211_ADDR_COPY(WH4(wh)->i_addr4, eh.ether_shost);
+			mc->mc_flags = 2;
+			IEEE80211_ADDR_COPY(mc->mc_addr5, eh.ether_shost);
+			IEEE80211_ADDR_COPY(mc->mc_addr6, eh.ether_shost);
+			break;
+		default:
+			KASSERT(0, ("meshae %d", meshae));
+			break;
+		}
+		mc->mc_ttl = 160;
+		seq = ieee80211_mesh_getseq();
+		mc->mc_seq[0] = seq & 0xff;
+		mc->mc_seq[1] = (seq >> 8) & 0xff;
+		mc->mc_seq[2] = (seq >> 16) & 0xff;
+		mc->mc_seq[3] = (seq >> 24) & 0xff;
 		break;
 	case IEEE80211_M_MONITOR:
 	case IEEE80211_M_WDS:		/* NB: is4addr should always be true */
@@ -1420,19 +1489,6 @@ ieee80211_encap(struct ieee80211vap *vap
 			    htole16(seqno << IEEE80211_SEQ_SEQ_SHIFT);
 			M_SEQNO_SET(m, seqno);
 		}
-		if (vap->iv_opmode == IEEE80211_M_MBSS) {
-			struct ieee80211_meshframe *mwh;
-			uint32_t seq;
-				
-			mwh = (struct ieee80211_meshframe *)wh;
-			mwh->i_mflags	= 0;	/* address extension bit */
-			mwh->i_mttl	= 160;
-			seq = ieee80211_mesh_getseq();
-			mwh->i_mseq[0] = seq & 0xff;
-			mwh->i_mseq[1] = (seq >> 8) & 0xff;
-			mwh->i_mseq[2] = (seq >> 16) & 0xff;
-			mwh->i_mseq[3] = (seq >> 24) & 0xff;
-		}
 	} else {
 		seqno = ni->ni_txseqs[IEEE80211_NONQOS_TID]++;
 		*(uint16_t *)wh->i_seq =



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