From owner-svn-src-head@FreeBSD.ORG Sun Oct 26 00:46:17 2008 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id A560B106567E; Sun, 26 Oct 2008 00:46:17 +0000 (UTC) (envelope-from sam@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 947238FC1A; Sun, 26 Oct 2008 00:46:17 +0000 (UTC) (envelope-from sam@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id m9Q0kH7k064996; Sun, 26 Oct 2008 00:46:17 GMT (envelope-from sam@svn.freebsd.org) Received: (from sam@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id m9Q0kHqZ064995; Sun, 26 Oct 2008 00:46:17 GMT (envelope-from sam@svn.freebsd.org) Message-Id: <200810260046.m9Q0kHqZ064995@svn.freebsd.org> From: Sam Leffler Date: Sun, 26 Oct 2008 00:46:17 +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: r184283 - 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, 26 Oct 2008 00:46:17 -0000 Author: sam Date: Sun Oct 26 00:46:17 2008 New Revision: 184283 URL: http://svn.freebsd.org/changeset/base/184283 Log: change ieee80211_send_nulldata to send a QoS Null Data frame to a QoS-enabled station; this makes inactivity handling follow the spec as previously it would probe inactive stations w/ a Null Data (no QoS) data frame Modified: head/sys/net80211/ieee80211_output.c Modified: head/sys/net80211/ieee80211_output.c ============================================================================== --- head/sys/net80211/ieee80211_output.c Sun Oct 26 00:43:11 2008 (r184282) +++ head/sys/net80211/ieee80211_output.c Sun Oct 26 00:46:17 2008 (r184283) @@ -530,7 +530,9 @@ ieee80211_mgmt_output(struct ieee80211_n } /* - * 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 @@ -546,6 +548,8 @@ ieee80211_send_nulldata(struct ieee80211 struct ieee80211com *ic = ni->ni_ic; struct mbuf *m; struct ieee80211_frame *wh; + int hdrlen; + uint8_t *frm; if (vap->iv_state == IEEE80211_S_CAC) { IEEE80211_NOTE(vap, IEEE80211_MSG_OUTPUT | IEEE80211_MSG_DOTH, @@ -555,37 +559,70 @@ ieee80211_send_nulldata(struct ieee80211 return EIO; /* XXX */ } - m = m_gethdr(M_NOWAIT, MT_HEADER); + 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 */ ieee80211_unref_node(&ni); vap->iv_stats.is_tx_nobuf++; return ENOMEM; } - MH_ALIGN(m, sizeof(struct ieee80211_frame)); + KASSERT(M_LEADINGSPACE(m) >= hdrlen, + ("leading space %zd", M_LEADINGSPACE(m))); + M_PREPEND(m, hdrlen, M_DONTWAIT); + if (m == NULL) { + /* NB: cannot happen */ + ieee80211_free_node(ni); + return ENOMEM; + } - wh = mtod(m, struct ieee80211_frame *); - 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); + wh = mtod(m, struct ieee80211_frame *); /* NB: a little lie */ + 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) && vap->iv_opmode != IEEE80211_M_HOSTAP) wh->i_fc[1] |= IEEE80211_FC1_PWR_MGT; - m->m_len = m->m_pkthdr.len = sizeof(struct ieee80211_frame); - } else { - /* NB: 4-address frame */ - m->m_len = m->m_pkthdr.len = - sizeof(struct ieee80211_frame_addr4); } + m->m_len = m->m_pkthdr.len = hdrlen; + M_WME_SETAC(m, WME_AC_BE); 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");