Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 3 Oct 2008 21:26:09 GMT
From:      Sam Leffler <sam@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 150901 for review
Message-ID:  <200810032126.m93LQ9fD090638@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=150901

Change 150901 by sam@sam_ebb on 2008/10/03 21:25:09

	make ieee80211_send_nulldata send a QoS null data frame when a station
	is setup w/ QoS; the spec says we should not be sending non-QoS frames

Affected files ...

.. //depot/projects/vap/sys/net80211/ieee80211_output.c#61 edit

Differences ...

==== //depot/projects/vap/sys/net80211/ieee80211_output.c#61 (text+ko) ====

@@ -406,15 +406,14 @@
 
 /*
  * Set the direction field and address fields of an outgoing
- * non-QoS frame.  Note this should be called early on in
- * constructing a frame as it sets i_fc[1]; other bits can
- * then be or'd in.
+ * frame.  Note this should be called early on in constructing
+ * a frame as it sets i_fc[1]; other bits can then be or'd in.
  */
 static void
 ieee80211_send_setup(
 	struct ieee80211_node *ni,
 	struct ieee80211_frame *wh,
-	int type,
+	int type, int tid,
 	const uint8_t sa[IEEE80211_ADDR_LEN],
 	const uint8_t da[IEEE80211_ADDR_LEN],
 	const uint8_t bssid[IEEE80211_ADDR_LEN])
@@ -462,11 +461,9 @@
 		IEEE80211_ADDR_COPY(wh->i_addr3, bssid);
 	}
 	*(uint16_t *)&wh->i_dur[0] = 0;
-	/* XXX probe response use per-vap seq#? */
-	/* NB: use non-QoS tid */
 	*(uint16_t *)&wh->i_seq[0] =
-	    htole16(ni->ni_txseqs[IEEE80211_NONQOS_TID] << IEEE80211_SEQ_SEQ_SHIFT);
-	ni->ni_txseqs[IEEE80211_NONQOS_TID]++;
+	    htole16(ni->ni_txseqs[tid] << IEEE80211_SEQ_SEQ_SHIFT);
+	ni->ni_txseqs[tid]++;
 #undef WH4
 }
 
@@ -507,9 +504,9 @@
 	}
 
 	wh = mtod(m, struct ieee80211_frame *);
-	ieee80211_send_setup(ni, wh, 
-		IEEE80211_FC0_TYPE_MGT | type,
-		vap->iv_myaddr, ni->ni_macaddr, ni->ni_bssid);
+	ieee80211_send_setup(ni, wh,
+	     IEEE80211_FC0_TYPE_MGT | type, IEEE80211_NONQOS_TID,
+	     vap->iv_myaddr, ni->ni_macaddr, ni->ni_bssid);
 	if (params->ibp_flags & IEEE80211_BPF_CRYPTO) {
 		IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_AUTH, wh->i_addr1,
 		    "encrypting frame (%s)", __func__);
@@ -538,7 +535,9 @@
 }
 
 /*
- * Send a null data frame to the specified node.
+ * Send a null data frame to the specified node.  If the station
+ * is setup for QoS then a QoS Null Data frame is constructed.
+ * If this is a WDS station then a 4-address frame is constructed.
  *
  * NB: the caller is assumed to have setup a node reference
  *     for use; this is necessary to deal with a race condition
@@ -565,10 +564,16 @@
 		return EIO;		/* XXX */
 	}
 
-	if (vap->iv_opmode == IEEE80211_M_WDS)
-		hdrlen = sizeof(struct ieee80211_frame_addr4);
+	if (ni->ni_flags & (IEEE80211_NODE_QOS|IEEE80211_NODE_HT))
+		hdrlen = sizeof(struct ieee80211_qosframe);
 	else
 		hdrlen = sizeof(struct ieee80211_frame);
+	/* NB: only WDS vap's get 4-address frames */
+	if (vap->iv_opmode == IEEE80211_M_WDS)
+		hdrlen += IEEE80211_ADDR_LEN;
+	if (ic->ic_flags & IEEE80211_F_DATAPAD)
+		hdrlen = roundup(hdrlen, sizeof(uint32_t));
+
 	m = ieee80211_getmgtframe(&frm, ic->ic_headroom + hdrlen, 0);
 	if (m == NULL) {
 		/* XXX debug msg */
@@ -586,9 +591,28 @@
 	}
 
 	wh = mtod(m, struct ieee80211_frame *);		/* NB: a little lie */
-	ieee80211_send_setup(ni, wh,
-		IEEE80211_FC0_TYPE_DATA | IEEE80211_FC0_SUBTYPE_NODATA,
-		vap->iv_myaddr, ni->ni_macaddr, ni->ni_bssid);
+	if (ni->ni_flags & IEEE80211_NODE_QOS) {
+		const int tid = WME_AC_TO_TID(WME_AC_BE);
+		uint8_t *qos;
+
+		ieee80211_send_setup(ni, wh,
+		    IEEE80211_FC0_TYPE_DATA | IEEE80211_FC0_SUBTYPE_QOS_NULL,
+		    tid, vap->iv_myaddr, ni->ni_macaddr, ni->ni_bssid);
+
+		if (vap->iv_opmode == IEEE80211_M_WDS)
+			qos = ((struct ieee80211_qosframe_addr4 *) wh)->i_qos;
+		else
+			qos = ((struct ieee80211_qosframe *) wh)->i_qos;
+		qos[0] = tid & IEEE80211_QOS_TID;
+		if (ic->ic_wme.wme_wmeChanParams.cap_wmeParams[WME_AC_BE].wmep_noackPolicy)
+			qos[0] |= IEEE80211_QOS_ACKPOLICY_NOACK;
+		qos[1] = 0;
+	} else {
+		ieee80211_send_setup(ni, wh,
+		    IEEE80211_FC0_TYPE_DATA | IEEE80211_FC0_SUBTYPE_NODATA,
+		    IEEE80211_NONQOS_TID,
+		    vap->iv_myaddr, ni->ni_macaddr, ni->ni_bssid);
+	}
 	if (vap->iv_opmode != IEEE80211_M_WDS) {
 		/* NB: power management bit is never sent by an AP */
 		if ((ni->ni_flags & IEEE80211_NODE_PWR_MGT) &&
@@ -603,7 +627,8 @@
 	IEEE80211_NODE_STAT(ni, tx_data);
 
 	IEEE80211_NOTE(vap, IEEE80211_MSG_DEBUG | IEEE80211_MSG_DUMPPKTS, ni,
-	    "send null data frame on channel %u, pwr mgt %s",
+	    "send %snull data frame on channel %u, pwr mgt %s",
+	    ni->ni_flags & IEEE80211_NODE_QOS ? "QoS " : "",
 	    ieee80211_chan2ieee(ic, ic->ic_curchan),
 	    wh->i_fc[1] & IEEE80211_FC1_PWR_MGT ? "ena" : "dis");
 
@@ -1751,8 +1776,8 @@
 
 	wh = mtod(m, struct ieee80211_frame *);
 	ieee80211_send_setup(ni, wh,
-		IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_PROBE_REQ,
-		sa, da, bssid);
+	     IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_PROBE_REQ,
+	     IEEE80211_NONQOS_TID, sa, da, bssid);
 	/* XXX power management? */
 	m->m_flags |= M_ENCAP;		/* mark encapsulated */
 
@@ -2341,8 +2366,8 @@
 
 	wh = mtod(m, struct ieee80211_frame *);
 	ieee80211_send_setup(bss, wh,
-		IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_PROBE_RESP,
-		vap->iv_myaddr, da, bss->ni_bssid);
+	     IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_PROBE_RESP,
+	     IEEE80211_NONQOS_TID, vap->iv_myaddr, da, bss->ni_bssid);
 	/* XXX power management? */
 	m->m_flags |= M_ENCAP;		/* mark encapsulated */
 



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