From owner-svn-src-head@FreeBSD.ORG Sun Mar 4 05:52:27 2012 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id A6CEA106564A; Sun, 4 Mar 2012 05:52:27 +0000 (UTC) (envelope-from adrian@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 960778FC19; Sun, 4 Mar 2012 05:52:27 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q245qR7d016847; Sun, 4 Mar 2012 05:52:27 GMT (envelope-from adrian@svn.freebsd.org) Received: (from adrian@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q245qRmA016843; Sun, 4 Mar 2012 05:52:27 GMT (envelope-from adrian@svn.freebsd.org) Message-Id: <201203040552.q245qRmA016843@svn.freebsd.org> From: Adrian Chadd Date: Sun, 4 Mar 2012 05:52:27 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r232480 - head/sys/net80211 X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 04 Mar 2012 05:52:27 -0000 Author: adrian Date: Sun Mar 4 05:52:26 2012 New Revision: 232480 URL: http://svn.freebsd.org/changeset/base/232480 Log: * Introduce new flag for QoS control field; * Change in mesh_input to validate that QoS is set and Mesh Control field is present, also both bytes of the QoS are read; * Moved defragmentation in mesh_input before we try to forward packet as inferred from amendment spec, because Mesh Control field only present in first fragment; * Changed in ieee80211_encap to set QoS subtype and Mesh Control field present, only first fragment have Mesh Control field present bit equal to 1; Submitted by: monthadar@gmail.com Modified: head/sys/net80211/ieee80211.h head/sys/net80211/ieee80211_mesh.c head/sys/net80211/ieee80211_output.c Modified: head/sys/net80211/ieee80211.h ============================================================================== --- head/sys/net80211/ieee80211.h Sun Mar 4 05:49:39 2012 (r232479) +++ head/sys/net80211/ieee80211.h Sun Mar 4 05:52:26 2012 (r232480) @@ -199,6 +199,13 @@ struct ieee80211_qosframe_addr4 { #define IEEE80211_QOS_EOSP 0x10 /* EndOfService Period*/ #define IEEE80211_QOS_EOSP_S 4 #define IEEE80211_QOS_TID 0x0f +/* qos[1] byte used for all frames sent by mesh STAs in a mesh BSS */ +#define IEEE80211_QOS_MC 0x10 /* Mesh control */ +/* Mesh power save level*/ +#define IEEE80211_QOS_MESH_PSL 0x20 +/* Mesh Receiver Service Period Initiated */ +#define IEEE80211_QOS_RSPI 0x40 +/* bits 11 to 15 reserved */ /* does frame have QoS sequence control data */ #define IEEE80211_QOS_HAS_SEQ(wh) \ Modified: head/sys/net80211/ieee80211_mesh.c ============================================================================== --- head/sys/net80211/ieee80211_mesh.c Sun Mar 4 05:49:39 2012 (r232479) +++ head/sys/net80211/ieee80211_mesh.c Sun Mar 4 05:52:26 2012 (r232480) @@ -1040,9 +1040,9 @@ mesh_input(struct ieee80211_node *ni, st struct ieee80211_frame *wh; const struct ieee80211_meshcntl *mc; int hdrspace, meshdrlen, need_tap; - uint8_t dir, type, subtype, qos; + uint8_t dir, type, subtype; uint32_t seq; - uint8_t *addr; + uint8_t *addr, qos[2]; ieee80211_seq rxseq; KASSERT(ni != NULL, ("null node")); @@ -1139,8 +1139,64 @@ mesh_input(struct ieee80211_node *ni, st vap->iv_stats.is_rx_wrongdir++; goto err; } - /* pull up enough to get to the mesh control */ + + /* All Mesh data frames are QoS subtype */ + if (!HAS_SEQ(type)) { + IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT, + wh, "data", "incorrect subtype 0x%x", subtype); + vap->iv_stats.is_rx_badsubtype++; + goto err; + } + + /* + * Next up, any fragmentation. + * XXX: we defrag before we even try to forward, + * Mesh Control field is not present in sub-sequent + * fragmented frames. This is in contrast to Draft 4.0. + */ hdrspace = ieee80211_hdrspace(ic, wh); + if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) { + m = ieee80211_defrag(ni, m, hdrspace); + if (m == NULL) { + /* Fragment dropped or frame not complete yet */ + goto out; + } + } + wh = mtod(m, struct ieee80211_frame *); /* NB: after defrag */ + + /* + * Now we have a complete Mesh Data frame. + */ + + /* + * Only fromDStoDS data frames use 4 address qos frames + * as specified in amendment. Otherwise addr4 is located + * in the Mesh Control field and a 3 address qos frame + * is used. + */ + if (IEEE80211_IS_DSTODS(wh)) + *(uint16_t *)qos = *(uint16_t *) + ((struct ieee80211_qosframe_addr4 *)wh)->i_qos; + else + *(uint16_t *)qos = *(uint16_t *) + ((struct ieee80211_qosframe *)wh)->i_qos; + + /* + * NB: The mesh STA sets the Mesh Control Present + * subfield to 1 in the Mesh Data frame containing + * an unfragmented MSDU, an A-MSDU, or the first + * fragment of an MSDU. + * After defrag it should always be present. + */ + if (!(qos[1] & IEEE80211_QOS_MC)) { + IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_MESH, + ni->ni_macaddr, NULL, + "%s", "Mesh control field not present"); + vap->iv_stats.is_rx_elem_missing++; /* XXX: kinda */ + goto err; + } + + /* pull up enough to get to the mesh control */ if (m->m_len < hdrspace + sizeof(struct ieee80211_meshcntl) && (m = m_pullup(m, hdrspace + sizeof(struct ieee80211_meshcntl))) == NULL) { @@ -1188,27 +1244,6 @@ mesh_input(struct ieee80211_node *ni, st /* NB: fall thru to deliver mcast frames locally */ } - /* - * Save QoS bits for use below--before we strip the header. - */ - if (subtype == IEEE80211_FC0_SUBTYPE_QOS) { - qos = (dir == IEEE80211_FC1_DIR_DSTODS) ? - ((struct ieee80211_qosframe_addr4 *)wh)->i_qos[0] : - ((struct ieee80211_qosframe *)wh)->i_qos[0]; - } else - qos = 0; - /* - * Next up, any fragmentation. - */ - if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) { - m = ieee80211_defrag(ni, m, hdrspace); - if (m == NULL) { - /* Fragment dropped or frame not complete yet */ - goto out; - } - } - wh = NULL; /* no longer valid, catch any uses */ - if (ieee80211_radiotap_active_vap(vap)) ieee80211_radiotap_rx(vap, m); need_tap = 0; @@ -1229,7 +1264,7 @@ mesh_input(struct ieee80211_node *ni, st IEEE80211_NODE_STAT(ni, rx_decap); goto err; } - if (qos & IEEE80211_QOS_AMSDU) { + if (qos[0] & IEEE80211_QOS_AMSDU) { m = ieee80211_decap_amsdu(ni, m); if (m == NULL) return IEEE80211_FC0_TYPE_DATA; Modified: head/sys/net80211/ieee80211_output.c ============================================================================== --- head/sys/net80211/ieee80211_output.c Sun Mar 4 05:49:39 2012 (r232479) +++ head/sys/net80211/ieee80211_output.c Sun Mar 4 05:52:26 2012 (r232480) @@ -1074,9 +1074,11 @@ ieee80211_encap(struct ieee80211vap *vap * ap's require all data frames to be QoS-encapsulated * once negotiated in which case we'll need to make this * configurable. + * NB: mesh data frames are QoS. */ - addqos = (ni->ni_flags & (IEEE80211_NODE_QOS|IEEE80211_NODE_HT)) && - (m->m_flags & M_EAPOL) == 0; + addqos = ((ni->ni_flags & (IEEE80211_NODE_QOS|IEEE80211_NODE_HT)) || + (vap->iv_opmode == IEEE80211_M_MBSS)) && + (m->m_flags & M_EAPOL) == 0; if (addqos) hdrsize = sizeof(struct ieee80211_qosframe); else @@ -1282,7 +1284,12 @@ ieee80211_encap(struct ieee80211vap *vap qos[0] = tid & IEEE80211_QOS_TID; if (ic->ic_wme.wme_wmeChanParams.cap_wmeParams[ac].wmep_noackPolicy) qos[0] |= IEEE80211_QOS_ACKPOLICY_NOACK; - qos[1] = 0; +#ifdef IEEE80211_SUPPORT_MESH + if (vap->iv_opmode == IEEE80211_M_MBSS) { + qos[1] |= IEEE80211_QOS_MC; + } else +#endif + qos[1] = 0; wh->i_fc[0] |= IEEE80211_FC0_SUBTYPE_QOS; if ((m->m_flags & M_AMPDU_MPDU) == 0) { @@ -1407,9 +1414,20 @@ ieee80211_fragment(struct ieee80211vap * * we mark the first fragment with the MORE_FRAG bit * it automatically is propagated to each fragment; we * need only clear it on the last fragment (done below). + * NB: frag 1+ dont have Mesh Control field present. */ whf = mtod(m, struct ieee80211_frame *); memcpy(whf, wh, hdrsize); +#ifdef IEEE80211_SUPPORT_MESH + if (vap->iv_opmode == IEEE80211_M_MBSS) { + if (IEEE80211_IS_DSTODS(wh)) + ((struct ieee80211_qosframe_addr4 *) + whf)->i_qos[1] &= ~IEEE80211_QOS_MC; + else + ((struct ieee80211_qosframe *) + whf)->i_qos[1] &= ~IEEE80211_QOS_MC; + } +#endif *(uint16_t *)&whf->i_seq[0] |= htole16( (fragno & IEEE80211_SEQ_FRAG_MASK) << IEEE80211_SEQ_FRAG_SHIFT);