Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 12 May 2015 16:55:51 +0000 (UTC)
From:      Adrian Chadd <adrian@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r282820 - head/sys/net80211
Message-ID:  <201505121655.t4CGtpsx068838@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: adrian
Date: Tue May 12 16:55:50 2015
New Revision: 282820
URL: https://svnweb.freebsd.org/changeset/base/282820

Log:
  Do not check sequence number for QoS Null frames; set it for generated QoS Null
  frames to 0
  
  From IEEE Std. 802.11-2012, 8.3.2.1 "Data frame format", p. 415 (513):
  "The Sequence Control field for QoS (+)Null frames is ignored by the receiver
  upon reception."
  
  At this moment, any <mode>_input() function interprets them as regular QoS data
  frames with TID = 0. As a result, stations, that use another TX sequence for
  QoS Null frames (e.g. wpi(4), where (QoS) Null frames are generated by the
  firmware), may experience significant packet loss with any other NIC in hostap
  mode.
  
  Tested:
  
  * wpi(4) (author)
  * iwn(4) - Intel 5100, STA mode (me)
  
  PR:		kern/200128
  Submitted by:	Andriy Voskoboinyk <s3erios@gmail.com>

Modified:
  head/sys/net80211/ieee80211.h
  head/sys/net80211/ieee80211_adhoc.c
  head/sys/net80211/ieee80211_hostap.c
  head/sys/net80211/ieee80211_input.h
  head/sys/net80211/ieee80211_output.c
  head/sys/net80211/ieee80211_sta.c
  head/sys/net80211/ieee80211_wds.c

Modified: head/sys/net80211/ieee80211.h
==============================================================================
--- head/sys/net80211/ieee80211.h	Tue May 12 16:36:54 2015	(r282819)
+++ head/sys/net80211/ieee80211.h	Tue May 12 16:55:50 2015	(r282820)
@@ -169,6 +169,11 @@ struct ieee80211_qosframe_addr4 {
 #define	IEEE80211_FC1_PROTECTED			0x40
 #define	IEEE80211_FC1_ORDER			0x80
 
+#define IEEE80211_HAS_SEQ(type, subtype) \
+	((type) != IEEE80211_FC0_TYPE_CTL && \
+	!((type) == IEEE80211_FC0_TYPE_DATA && \
+	 ((subtype) & IEEE80211_FC0_SUBTYPE_QOS_NULL) == \
+		      IEEE80211_FC0_SUBTYPE_QOS_NULL))
 #define	IEEE80211_SEQ_FRAG_MASK			0x000f
 #define	IEEE80211_SEQ_FRAG_SHIFT		0
 #define	IEEE80211_SEQ_SEQ_MASK			0xfff0

Modified: head/sys/net80211/ieee80211_adhoc.c
==============================================================================
--- head/sys/net80211/ieee80211_adhoc.c	Tue May 12 16:36:54 2015	(r282819)
+++ head/sys/net80211/ieee80211_adhoc.c	Tue May 12 16:55:50 2015	(r282820)
@@ -291,7 +291,6 @@ doprint(struct ieee80211vap *vap, int su
 static int
 adhoc_input(struct ieee80211_node *ni, struct mbuf *m, int rssi, int nf)
 {
-#define	HAS_SEQ(type)	((type & 0x4) == 0)
 	struct ieee80211vap *vap = ni->ni_vap;
 	struct ieee80211com *ic = ni->ni_ic;
 	struct ifnet *ifp = vap->iv_ifp;
@@ -414,7 +413,8 @@ adhoc_input(struct ieee80211_node *ni, s
 		}
 		IEEE80211_RSSI_LPF(ni->ni_avgrssi, rssi);
 		ni->ni_noise = nf;
-		if (HAS_SEQ(type) && IEEE80211_ADDR_EQ(wh->i_addr2, ni->ni_macaddr)) {
+		if (IEEE80211_HAS_SEQ(type, subtype) &&
+		    IEEE80211_ADDR_EQ(wh->i_addr2, ni->ni_macaddr)) {
 			uint8_t tid = ieee80211_gettid(wh);
 			if (IEEE80211_QOS_HAS_SEQ(wh) &&
 			    TID_TO_WME_AC(tid) >= WME_AC_VI)

Modified: head/sys/net80211/ieee80211_hostap.c
==============================================================================
--- head/sys/net80211/ieee80211_hostap.c	Tue May 12 16:36:54 2015	(r282819)
+++ head/sys/net80211/ieee80211_hostap.c	Tue May 12 16:55:50 2015	(r282820)
@@ -478,7 +478,6 @@ doprint(struct ieee80211vap *vap, int su
 static int
 hostap_input(struct ieee80211_node *ni, struct mbuf *m, int rssi, int nf)
 {
-#define	HAS_SEQ(type)	((type & 0x4) == 0)
 	struct ieee80211vap *vap = ni->ni_vap;
 	struct ieee80211com *ic = ni->ni_ic;
 	struct ifnet *ifp = vap->iv_ifp;
@@ -571,7 +570,7 @@ hostap_input(struct ieee80211_node *ni, 
 
 		IEEE80211_RSSI_LPF(ni->ni_avgrssi, rssi);
 		ni->ni_noise = nf;
-		if (HAS_SEQ(type)) {
+		if (IEEE80211_HAS_SEQ(type, subtype)) {
 			uint8_t tid = ieee80211_gettid(wh);
 			if (IEEE80211_QOS_HAS_SEQ(wh) &&
 			    TID_TO_WME_AC(tid) >= WME_AC_VI)

Modified: head/sys/net80211/ieee80211_input.h
==============================================================================
--- head/sys/net80211/ieee80211_input.h	Tue May 12 16:36:54 2015	(r282819)
+++ head/sys/net80211/ieee80211_input.h	Tue May 12 16:55:50 2015	(r282820)
@@ -168,19 +168,22 @@ ieee80211_check_rxseq(struct ieee80211_n
 {
 #define	SEQ_LEQ(a,b)	((int)((a)-(b)) <= 0)
 #define	SEQ_EQ(a,b)	((int)((a)-(b)) == 0)
-#define	HAS_SEQ(type)	((type & 0x4) == 0)
 #define	SEQNO(a)	((a) >> IEEE80211_SEQ_SEQ_SHIFT)
 #define	FRAGNO(a)	((a) & IEEE80211_SEQ_FRAG_MASK)
 	uint16_t rxseq;
-	uint8_t type;
+	uint8_t type, subtype;
 	uint8_t tid;
 	struct ieee80211_rx_ampdu *rap;
 
 	rxseq = le16toh(*(uint16_t *)wh->i_seq);
 	type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
+	subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
 
-	/* Types with no sequence number are always treated valid */
-	if (! HAS_SEQ(type))
+	/*
+	 * Types with no sequence number (or QoS (+)Null frames)
+	 * are always treated valid.
+	 */
+	if (! IEEE80211_HAS_SEQ(type, subtype))
 		return 1;
 
 	tid = ieee80211_gettid(wh);
@@ -235,7 +238,6 @@ ieee80211_check_rxseq(struct ieee80211_n
 	return 1;
 #undef	SEQ_LEQ
 #undef	SEQ_EQ
-#undef	HAS_SEQ
 #undef	SEQNO
 #undef	FRAGNO
 }

Modified: head/sys/net80211/ieee80211_output.c
==============================================================================
--- head/sys/net80211/ieee80211_output.c	Tue May 12 16:36:54 2015	(r282819)
+++ head/sys/net80211/ieee80211_output.c	Tue May 12 16:55:50 2015	(r282820)
@@ -730,7 +730,12 @@ ieee80211_send_setup(
 	if (tid != IEEE80211_NONQOS_TID && IEEE80211_AMPDU_RUNNING(tap))
 		m->m_flags |= M_AMPDU_MPDU;
 	else {
-		seqno = ni->ni_txseqs[tid]++;
+		if (IEEE80211_HAS_SEQ(type & IEEE80211_FC0_TYPE_MASK,
+				      type & IEEE80211_FC0_SUBTYPE_MASK))
+			seqno = ni->ni_txseqs[tid]++;
+		else
+			seqno = 0;
+
 		*(uint16_t *)&wh->i_seq[0] =
 		    htole16(seqno << IEEE80211_SEQ_SEQ_SHIFT);
 		M_SEQNO_SET(m, seqno);

Modified: head/sys/net80211/ieee80211_sta.c
==============================================================================
--- head/sys/net80211/ieee80211_sta.c	Tue May 12 16:36:54 2015	(r282819)
+++ head/sys/net80211/ieee80211_sta.c	Tue May 12 16:55:50 2015	(r282820)
@@ -527,7 +527,6 @@ doprint(struct ieee80211vap *vap, int su
 static int
 sta_input(struct ieee80211_node *ni, struct mbuf *m, int rssi, int nf)
 {
-#define	HAS_SEQ(type)	((type & 0x4) == 0)
 	struct ieee80211vap *vap = ni->ni_vap;
 	struct ieee80211com *ic = ni->ni_ic;
 	struct ifnet *ifp = vap->iv_ifp;
@@ -623,7 +622,8 @@ sta_input(struct ieee80211_node *ni, str
 
 		IEEE80211_RSSI_LPF(ni->ni_avgrssi, rssi);
 		ni->ni_noise = nf;
-		if (HAS_SEQ(type) && !IEEE80211_IS_MULTICAST(wh->i_addr1)) {
+		if ( IEEE80211_HAS_SEQ(type, subtype) &&
+		    !IEEE80211_IS_MULTICAST(wh->i_addr1)) {
 			uint8_t tid = ieee80211_gettid(wh);
 			if (IEEE80211_QOS_HAS_SEQ(wh) &&
 			    TID_TO_WME_AC(tid) >= WME_AC_VI)

Modified: head/sys/net80211/ieee80211_wds.c
==============================================================================
--- head/sys/net80211/ieee80211_wds.c	Tue May 12 16:36:54 2015	(r282819)
+++ head/sys/net80211/ieee80211_wds.c	Tue May 12 16:55:50 2015	(r282820)
@@ -406,7 +406,6 @@ wds_newstate(struct ieee80211vap *vap, e
 static int
 wds_input(struct ieee80211_node *ni, struct mbuf *m, int rssi, int nf)
 {
-#define	HAS_SEQ(type)	((type & 0x4) == 0)
 	struct ieee80211vap *vap = ni->ni_vap;
 	struct ieee80211com *ic = ni->ni_ic;
 	struct ifnet *ifp = vap->iv_ifp;
@@ -488,7 +487,7 @@ wds_input(struct ieee80211_node *ni, str
 	}
 	IEEE80211_RSSI_LPF(ni->ni_avgrssi, rssi);
 	ni->ni_noise = nf;
-	if (HAS_SEQ(type)) {
+	if (IEEE80211_HAS_SEQ(type, subtype)) {
 		uint8_t tid = ieee80211_gettid(wh);
 		if (IEEE80211_QOS_HAS_SEQ(wh) &&
 		    TID_TO_WME_AC(tid) >= WME_AC_VI)



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