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>