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 <s3er...@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)
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to