From owner-svn-src-head@freebsd.org Fri Jun 5 07:38:11 2020 Return-Path: Delivered-To: svn-src-head@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id CD913343409; Fri, 5 Jun 2020 07:38:11 +0000 (UTC) (envelope-from adrian@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 49dZJ356cxz4KrH; Fri, 5 Jun 2020 07:38:11 +0000 (UTC) (envelope-from adrian@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id AADD4D6F3; Fri, 5 Jun 2020 07:38:11 +0000 (UTC) (envelope-from adrian@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id 0557cBTO085835; Fri, 5 Jun 2020 07:38:11 GMT (envelope-from adrian@FreeBSD.org) Received: (from adrian@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id 0557cBWA085832; Fri, 5 Jun 2020 07:38:11 GMT (envelope-from adrian@FreeBSD.org) Message-Id: <202006050738.0557cBWA085832@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: adrian set sender to adrian@FreeBSD.org using -f From: Adrian Chadd Date: Fri, 5 Jun 2020 07:38:11 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r361825 - head/sys/net80211 X-SVN-Group: head X-SVN-Commit-Author: adrian X-SVN-Commit-Paths: head/sys/net80211 X-SVN-Commit-Revision: 361825 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.33 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: Fri, 05 Jun 2020 07:38:11 -0000 Author: adrian Date: Fri Jun 5 07:38:10 2020 New Revision: 361825 URL: https://svnweb.freebsd.org/changeset/base/361825 Log: [net80211] Add initial A-MSDU in A-MPDU negotation support. This is hopefully a big no-op unless you're running some extra patches to flip on A-MSDU options in a driver. 802.11n supports sending A-MSDU in A-MPDU. That lets you do things like pack small frames into an A-MSDU and stuff /those/ into an A-MPDU. It allows for much more efficient airtime because you're not wasting time sending small frames - which is still a problem when doing A-MPDU as there's still per-frame overhead and minimum A-MPDU density requirements. It, however, is optional for 802.11n. A lot of stuff doesn't advertise it (but does it, just wait!); and I know that ath10k does it and my ath(4) driver work supports it. Now, 802.11ac makes A-MSDU in A-MPDU something that can happen more frequently, because even though you can send very large A-MPDUs (like 1 megabyte and larger) you still have the small frame problem. So, 802.11ac NICs like ath10k and iwm will support A-MSDU in A-MPDU out of the box if it's enabled - and you can negotiate it. So, let's lay down the ground work to enable A-MSDU in A-MPDU. This will allow hardware like iwn(4) and ath(4) which supports software A-MSDU but hardware A-MPDU to be more efficient. Drivers that support A-MSDU in A-MPDU will set TX/RX htcap flags. Note this is separate from the software A-MSDU encap path; /that/ dictates whether net80211 is doing A-MSDU encapsulation or not. These HTC flags control negotiation, NOT encapsulation. Once this negotiation and driver bits are done, hardware like rtwn(4), run(4), and others will be able to use A-MSDU even without A-MPDU working; right now FF and A-MSDU aren't even attempted if you're an 11n node. It's a small hold-over from the initial A-MPDU work and I know how to fix it, but to flip it on properly I need to be able to negotiate or ignore A-MSDU in A-MPDU. Oh and the fun part - some 11ac APs I've tested will quite happily decap A-MSDU in A-MPDU even though they don't negotiate it when doing 802.11n. So hey, I know it works - I just want to properly handle things. :-) Tested: * AR9380, STA/AP mode Modified: head/sys/net80211/_ieee80211.h head/sys/net80211/ieee80211_ht.c head/sys/net80211/ieee80211_ht.h Modified: head/sys/net80211/_ieee80211.h ============================================================================== --- head/sys/net80211/_ieee80211.h Fri Jun 5 07:37:52 2020 (r361824) +++ head/sys/net80211/_ieee80211.h Fri Jun 5 07:38:10 2020 (r361825) @@ -529,10 +529,13 @@ struct ieee80211_mimo_info { #define IEEE80211_HTC_TXUNEQUAL 0x00800000 /* CAPABILITY: TX unequal MCS */ #define IEEE80211_HTC_TXMCS32 0x01000000 /* CAPABILITY: MCS32 support */ #define IEEE80211_HTC_TXLDPC 0x02000000 /* CAPABILITY: TX using LDPC */ +#define IEEE80211_HTC_RX_AMSDU_AMPDU 0x04000000 /* CAPABILITY: RX A-MSDU in A-MPDU */ +#define IEEE80211_HTC_TX_AMSDU_AMPDU 0x08000000 /* CAPABILITY: TX A-MSDU in A-MPDU */ #define IEEE80211_C_HTCAP_BITS \ "\20\1LDPC\2CHWIDTH40\5GREENFIELD\6SHORTGI20\7SHORTGI40\10TXSTBC" \ - "\21AMPDU\22AMSDU\23HT\24SMPS\25RIFS\32TXLDPC" + "\21AMPDU\22AMSDU\23HT\24SMPS\25RIFS\32TXLDPC\33RXAMSDUAMPDU" \ + "\34TXAMSDUAMPDU" /* * RX status notification - which fields are valid. Modified: head/sys/net80211/ieee80211_ht.c ============================================================================== --- head/sys/net80211/ieee80211_ht.c Fri Jun 5 07:37:52 2020 (r361824) +++ head/sys/net80211/ieee80211_ht.c Fri Jun 5 07:38:10 2020 (r361825) @@ -592,6 +592,7 @@ static int ampdu_rx_start(struct ieee80211_node *ni, struct ieee80211_rx_ampdu *rap, int baparamset, int batimeout, int baseqctl) { + struct ieee80211vap *vap = ni->ni_vap; int bufsiz = MS(baparamset, IEEE80211_BAPS_BUFSIZ); if (rap->rxa_flags & IEEE80211_AGGR_RUNNING) { @@ -607,6 +608,13 @@ ampdu_rx_start(struct ieee80211_node *ni, struct ieee8 rap->rxa_start = MS(baseqctl, IEEE80211_BASEQ_START); rap->rxa_flags |= IEEE80211_AGGR_RUNNING | IEEE80211_AGGR_XCHGPEND; + /* XXX this should be a configuration flag */ + if ((vap->iv_htcaps & IEEE80211_HTC_RX_AMSDU_AMPDU) && + (MS(baparamset, IEEE80211_BAPS_AMSDU))) + rap->rxa_flags |= IEEE80211_AGGR_AMSDU; + else + rap->rxa_flags &= ~IEEE80211_AGGR_AMSDU; + return 0; } @@ -642,6 +650,8 @@ ieee80211_ampdu_rx_start_ext(struct ieee80211_node *ni } rap->rxa_flags |= IEEE80211_AGGR_RUNNING | IEEE80211_AGGR_XCHGPEND; + /* XXX TODO: no amsdu flag */ + IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_11N, ni, "%s: tid=%d, start=%d, wnd=%d, flags=0x%08x", __func__, @@ -1163,7 +1173,8 @@ ieee80211_ht_node_init(struct ieee80211_node *ni) ieee80211_txampdu_init_pps(tap); /* NB: further initialization deferred */ } - ni->ni_flags |= IEEE80211_NODE_HT | IEEE80211_NODE_AMPDU; + ni->ni_flags |= IEEE80211_NODE_HT | IEEE80211_NODE_AMPDU | + IEEE80211_NODE_AMSDU; } /* @@ -1329,7 +1340,8 @@ ieee80211_ht_wds_init(struct ieee80211_node *ni) ieee80211_txampdu_init_pps(tap); } /* NB: AMPDU tx/rx governed by IEEE80211_FHT_AMPDU_{TX,RX} */ - ni->ni_flags |= IEEE80211_NODE_HT | IEEE80211_NODE_AMPDU; + ni->ni_flags |= IEEE80211_NODE_HT | IEEE80211_NODE_AMPDU | + IEEE80211_NODE_AMSDU; } /* @@ -2173,6 +2185,7 @@ ieee80211_addba_response(struct ieee80211_node *ni, struct ieee80211_tx_ampdu *tap, int status, int baparamset, int batimeout) { + struct ieee80211vap *vap = ni->ni_vap; int bufsiz, tid; /* XXX locking */ @@ -2182,10 +2195,16 @@ ieee80211_addba_response(struct ieee80211_node *ni, /* XXX override our request? */ tap->txa_wnd = (bufsiz == 0) ? IEEE80211_AGGR_BAWMAX : min(bufsiz, IEEE80211_AGGR_BAWMAX); - /* XXX AC/TID */ tid = MS(baparamset, IEEE80211_BAPS_TID); tap->txa_flags |= IEEE80211_AGGR_RUNNING; tap->txa_attempts = 0; + /* TODO: this should be a vap flag */ + if ((vap->iv_htcaps & IEEE80211_HTC_TX_AMSDU_AMPDU) && + (ni->ni_flags & IEEE80211_NODE_AMSDU_TX) && + (MS(baparamset, IEEE80211_BAPS_AMSDU))) + tap->txa_flags |= IEEE80211_AGGR_AMSDU; + else + tap->txa_flags &= ~IEEE80211_AGGR_AMSDU; } else { /* mark tid so we don't try again */ tap->txa_flags |= IEEE80211_AGGR_NAK; @@ -2204,7 +2223,7 @@ ieee80211_addba_stop(struct ieee80211_node *ni, struct addba_stop_timeout(tap); if (tap->txa_flags & IEEE80211_AGGR_RUNNING) { /* XXX clear aggregation queue */ - tap->txa_flags &= ~IEEE80211_AGGR_RUNNING; + tap->txa_flags &= ~(IEEE80211_AGGR_RUNNING | IEEE80211_AGGR_AMSDU); } tap->txa_attempts = 0; } @@ -2256,7 +2275,7 @@ ht_recv_action_ba_addba_request(struct ieee80211_node */ if ((ni->ni_flags & IEEE80211_NODE_AMPDU_RX) && (vap->iv_flags_ht & IEEE80211_FHT_AMPDU_RX)) { - /* XXX handle ampdu_rx_start failure */ + /* XXX TODO: handle ampdu_rx_start failure */ ic->ic_ampdu_rx_start(ni, rap, baparamset, batimeout, baseqctl); @@ -2275,7 +2294,16 @@ ht_recv_action_ba_addba_request(struct ieee80211_node | SM(tid, IEEE80211_BAPS_TID) | SM(rap->rxa_wnd, IEEE80211_BAPS_BUFSIZ) ; - /* XXX AMSDU in AMPDU? */ + + /* + * TODO: we're out of iv_flags_ht fields; once + * this is extended we should make this configurable. + */ + if ((baparamset & IEEE80211_BAPS_AMSDU) && + (ni->ni_flags & IEEE80211_NODE_AMSDU_RX) && + (vap->iv_htcaps & IEEE80211_HTC_RX_AMSDU_AMPDU)) + args[2] |= IEEE80211_BAPS_AMSDU; + args[3] = 0; args[4] = 0; ic->ic_send_action(ni, IEEE80211_ACTION_CAT_BA, @@ -2294,6 +2322,7 @@ ht_recv_action_ba_addba_response(struct ieee80211_node uint8_t dialogtoken, policy; uint16_t baparamset, batimeout, code; int tid, bufsiz; + int amsdu; dialogtoken = frm[2]; code = le16dec(frm+3); @@ -2301,6 +2330,7 @@ ht_recv_action_ba_addba_response(struct ieee80211_node tid = MS(baparamset, IEEE80211_BAPS_TID); bufsiz = MS(baparamset, IEEE80211_BAPS_BUFSIZ); policy = MS(baparamset, IEEE80211_BAPS_POLICY); + amsdu = !! MS(baparamset, IEEE80211_BAPS_AMSDU); batimeout = le16dec(frm+7); tap = &ni->ni_tx_ampdu[tid]; @@ -2349,11 +2379,12 @@ ht_recv_action_ba_addba_response(struct ieee80211_node } #endif - /* XXX TODO: check AMSDU in AMPDU configuration */ IEEE80211_NOTE(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_11N, ni, "recv ADDBA response: dialogtoken %u code %d " - "baparamset 0x%x (tid %d bufsiz %d) batimeout %d", - dialogtoken, code, baparamset, tid, bufsiz, + "baparamset 0x%x (tid %d bufsiz %d amsdu %d) batimeout %d", + dialogtoken, code, baparamset, tid, + bufsiz, + amsdu, batimeout); ic->ic_addba_response(ni, tap, code, baparamset, batimeout); return 0; @@ -2510,8 +2541,12 @@ ieee80211_ampdu_request(struct ieee80211_node *ni, | SM(tid, IEEE80211_BAPS_TID) | SM(IEEE80211_AGGR_BAWMAX, IEEE80211_BAPS_BUFSIZ) ; - /* XXX TODO: check AMSDU in AMPDU configuration */ + /* XXX TODO: this should be a flag, not iv_htcaps */ + if ((ni->ni_flags & IEEE80211_NODE_AMSDU_TX) && + (ni->ni_vap->iv_htcaps & IEEE80211_HTC_TX_AMSDU_AMPDU)) + args[2] |= IEEE80211_BAPS_AMSDU; + args[3] = 0; /* batimeout */ /* NB: do first so there's no race against reply */ if (!ic->ic_addba_request(ni, tap, dialogtoken, args[2], args[3])) { @@ -2843,11 +2878,11 @@ ht_send_action_ba_addba(struct ieee80211_node *ni, IEEE80211_NOTE(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_11N, ni, "send ADDBA %s: dialogtoken %d status %d " - "baparamset 0x%x (tid %d) batimeout 0x%x baseqctl 0x%x", + "baparamset 0x%x (tid %d amsdu %d) batimeout 0x%x baseqctl 0x%x", (action == IEEE80211_ACTION_BA_ADDBA_REQUEST) ? "request" : "response", args[0], args[1], args[2], MS(args[2], IEEE80211_BAPS_TID), - args[3], args[4]); + MS(args[2], IEEE80211_BAPS_AMSDU), args[3], args[4]); IEEE80211_DPRINTF(vap, IEEE80211_MSG_NODE, "ieee80211_ref_node (%s:%u) %p<%s> refcnt %d\n", __func__, __LINE__, Modified: head/sys/net80211/ieee80211_ht.h ============================================================================== --- head/sys/net80211/ieee80211_ht.h Fri Jun 5 07:37:52 2020 (r361824) +++ head/sys/net80211/ieee80211_ht.h Fri Jun 5 07:38:10 2020 (r361825) @@ -47,6 +47,7 @@ struct ieee80211_tx_ampdu { #define IEEE80211_AGGR_NAK 0x0010 /* peer NAK'd ADDBA request */ #define IEEE80211_AGGR_BARPEND 0x0020 /* BAR response pending */ #define IEEE80211_AGGR_WAITRX 0x0040 /* Wait for first RX frame to define BAW */ +#define IEEE80211_AGGR_AMSDU 0x0080 /* A-MSDU in A-MPDU TX allowed */ uint8_t txa_tid; uint8_t txa_token; /* dialog token */ int txa_lastsample; /* ticks @ last traffic sample */ @@ -67,6 +68,14 @@ struct ieee80211_tx_ampdu { /* return non-zero if AMPDU tx for the TID is running */ #define IEEE80211_AMPDU_RUNNING(tap) \ (((tap)->txa_flags & IEEE80211_AGGR_RUNNING) != 0) + +/* + * Return non-zero if AMPDU tx for the TID is running and we can do + * A-MSDU in A-MPDU + */ +#define IEEE80211_AMPDU_RUNNING_AMSDU(tap) \ + ((((tap)->txa_flags & (IEEE80211_AGGR_RUNNING | IEEE80211_AGGR_AMSDU)) \ + == (IEEE80211_AGGR_RUNNING | IEEE80211_AGGR_AMSDU)) /* return non-zero if AMPDU tx for the TID was NACKed */ #define IEEE80211_AMPDU_NACKED(tap)\