PERFORCE change 150901 for review
Sam Leffler
sam at FreeBSD.org
Fri Oct 3 21:26:10 UTC 2008
http://perforce.freebsd.org/chv.cgi?CH=150901
Change 150901 by sam at 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 */
More information about the p4-projects
mailing list