svn commit: r193709 - projects/mesh11s/sys/net80211
Rui Paulo
rpaulo at FreeBSD.org
Mon Jun 8 11:39:04 UTC 2009
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 =
More information about the svn-src-projects
mailing list