1170530Ssam/*- 2178354Ssam * Copyright (c) 2007-2008 Sam Leffler, Errno Consulting 3170530Ssam * All rights reserved. 4170530Ssam * 5170530Ssam * Redistribution and use in source and binary forms, with or without 6170530Ssam * modification, are permitted provided that the following conditions 7170530Ssam * are met: 8170530Ssam * 1. Redistributions of source code must retain the above copyright 9170530Ssam * notice, this list of conditions and the following disclaimer. 10170530Ssam * 2. Redistributions in binary form must reproduce the above copyright 11170530Ssam * notice, this list of conditions and the following disclaimer in the 12170530Ssam * documentation and/or other materials provided with the distribution. 13170530Ssam * 14170530Ssam * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15170530Ssam * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16170530Ssam * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17170530Ssam * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18170530Ssam * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19170530Ssam * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20170530Ssam * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21170530Ssam * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22170530Ssam * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23170530Ssam * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24170530Ssam * 25170530Ssam * $FreeBSD: stable/11/sys/net80211/ieee80211_ht.h 330457 2018-03-05 08:17:02Z eadler $ 26170530Ssam */ 27170530Ssam#ifndef _NET80211_IEEE80211_HT_H_ 28170530Ssam#define _NET80211_IEEE80211_HT_H_ 29170530Ssam 30170530Ssam/* 31170530Ssam * 802.11n protocol implementation definitions. 32170530Ssam */ 33170530Ssam 34170530Ssam#define IEEE80211_AGGR_BAWMAX 64 /* max block ack window size */ 35173273Ssam/* threshold for aging overlapping non-HT bss */ 36173273Ssam#define IEEE80211_NONHT_PRESENT_AGE msecs_to_ticks(60*1000) 37170530Ssam 38170530Ssamstruct ieee80211_tx_ampdu { 39184280Ssam struct ieee80211_node *txa_ni; /* back pointer */ 40170530Ssam u_short txa_flags; 41170530Ssam#define IEEE80211_AGGR_IMMEDIATE 0x0001 /* BA policy */ 42170530Ssam#define IEEE80211_AGGR_XCHGPEND 0x0002 /* ADDBA response pending */ 43170530Ssam#define IEEE80211_AGGR_RUNNING 0x0004 /* ADDBA response received */ 44170530Ssam#define IEEE80211_AGGR_SETUP 0x0008 /* deferred state setup */ 45173273Ssam#define IEEE80211_AGGR_NAK 0x0010 /* peer NAK'd ADDBA request */ 46184280Ssam#define IEEE80211_AGGR_BARPEND 0x0020 /* BAR response pending */ 47234324Sadrian uint8_t txa_tid; 48170530Ssam uint8_t txa_token; /* dialog token */ 49178354Ssam int txa_lastsample; /* ticks @ last traffic sample */ 50178354Ssam int txa_pkts; /* packets over last sample interval */ 51178354Ssam int txa_avgpps; /* filtered traffic over window */ 52170530Ssam int txa_qbytes; /* data queued (bytes) */ 53170530Ssam short txa_qframes; /* data queued (frames) */ 54183245Ssam ieee80211_seq txa_start; /* BA window left edge */ 55183245Ssam ieee80211_seq txa_seqpending; /* new txa_start pending BAR response */ 56170530Ssam uint16_t txa_wnd; /* BA window size */ 57184280Ssam uint8_t txa_attempts; /* # ADDBA/BAR requests w/o a response*/ 58184280Ssam int txa_nextrequest;/* soonest to make next request */ 59170530Ssam struct callout txa_timer; 60175880Ssam void *txa_private; /* driver-private storage */ 61193239Ssam uint64_t txa_pad[4]; 62170530Ssam}; 63170530Ssam 64170530Ssam/* return non-zero if AMPDU tx for the TID is running */ 65170530Ssam#define IEEE80211_AMPDU_RUNNING(tap) \ 66170530Ssam (((tap)->txa_flags & IEEE80211_AGGR_RUNNING) != 0) 67170530Ssam 68297603Sadrian/* return non-zero if AMPDU tx for the TID was NACKed */ 69297603Sadrian#define IEEE80211_AMPDU_NACKED(tap)\ 70297603Sadrian (!! ((tap)->txa_flags & IEEE80211_AGGR_NAK)) 71297603Sadrian 72170530Ssam/* return non-zero if AMPDU tx for the TID is running or started */ 73170530Ssam#define IEEE80211_AMPDU_REQUESTED(tap) \ 74170530Ssam (((tap)->txa_flags & \ 75173273Ssam (IEEE80211_AGGR_RUNNING|IEEE80211_AGGR_XCHGPEND|IEEE80211_AGGR_NAK)) != 0) 76170530Ssam 77187797Ssam#define IEEE80211_AGGR_BITS \ 78187797Ssam "\20\1IMMEDIATE\2XCHGPEND\3RUNNING\4SETUP\5NAK" 79187797Ssam 80178354Ssam/* 81178354Ssam * Traffic estimator support. We estimate packets/sec for 82178354Ssam * each AC that is setup for AMPDU or will potentially be 83178354Ssam * setup for AMPDU. The traffic rate can be used to decide 84178354Ssam * when AMPDU should be setup (according to a threshold) 85178354Ssam * and is available for drivers to do things like cache 86178354Ssam * eviction when only a limited number of BA streams are 87178354Ssam * available and more streams are requested than available. 88178354Ssam */ 89178354Ssam 90178951Ssamstatic __inline void 91288315Sadrianieee80211_txampdu_init_pps(struct ieee80211_tx_ampdu *tap) 92288315Sadrian{ 93288315Sadrian /* 94288315Sadrian * Reset packet estimate. 95288315Sadrian */ 96288315Sadrian tap->txa_lastsample = ticks; 97288315Sadrian tap->txa_avgpps = 0; 98288315Sadrian} 99288315Sadrian 100288315Sadrianstatic __inline void 101178354Ssamieee80211_txampdu_update_pps(struct ieee80211_tx_ampdu *tap) 102178354Ssam{ 103288315Sadrian 104178354Ssam /* NB: scale factor of 2 was picked heuristically */ 105178354Ssam tap->txa_avgpps = ((tap->txa_avgpps << 2) - 106178354Ssam tap->txa_avgpps + tap->txa_pkts) >> 2; 107178354Ssam} 108178354Ssam 109178354Ssam/* 110178354Ssam * Count a packet towards the pps estimate. 111178354Ssam */ 112178951Ssamstatic __inline void 113178354Ssamieee80211_txampdu_count_packet(struct ieee80211_tx_ampdu *tap) 114178354Ssam{ 115288315Sadrian 116178354Ssam /* XXX bound loop/do more crude estimate? */ 117178354Ssam while (ticks - tap->txa_lastsample >= hz) { 118178354Ssam ieee80211_txampdu_update_pps(tap); 119178354Ssam /* reset to start new sample interval */ 120178354Ssam tap->txa_pkts = 0; 121178354Ssam if (tap->txa_avgpps == 0) { 122178354Ssam tap->txa_lastsample = ticks; 123178354Ssam break; 124178354Ssam } 125178354Ssam tap->txa_lastsample += hz; 126178354Ssam } 127178354Ssam tap->txa_pkts++; 128178354Ssam} 129178354Ssam 130178354Ssam/* 131178354Ssam * Get the current pps estimate. If the average is out of 132178354Ssam * date due to lack of traffic then we decay the estimate 133178354Ssam * to account for the idle time. 134178354Ssam */ 135178951Ssamstatic __inline int 136178354Ssamieee80211_txampdu_getpps(struct ieee80211_tx_ampdu *tap) 137178354Ssam{ 138178354Ssam /* XXX bound loop/do more crude estimate? */ 139178354Ssam while (ticks - tap->txa_lastsample >= hz) { 140178354Ssam ieee80211_txampdu_update_pps(tap); 141178354Ssam tap->txa_pkts = 0; 142178354Ssam if (tap->txa_avgpps == 0) { 143178354Ssam tap->txa_lastsample = ticks; 144178354Ssam break; 145178354Ssam } 146178354Ssam tap->txa_lastsample += hz; 147178354Ssam } 148178354Ssam return tap->txa_avgpps; 149178354Ssam} 150178354Ssam 151170530Ssamstruct ieee80211_rx_ampdu { 152170530Ssam int rxa_flags; 153170530Ssam int rxa_qbytes; /* data queued (bytes) */ 154170530Ssam short rxa_qframes; /* data queued (frames) */ 155170530Ssam ieee80211_seq rxa_seqstart; 156170530Ssam ieee80211_seq rxa_start; /* start of current BA window */ 157170530Ssam uint16_t rxa_wnd; /* BA window size */ 158173273Ssam int rxa_age; /* age of oldest frame in window */ 159173273Ssam int rxa_nframes; /* frames since ADDBA */ 160170530Ssam struct mbuf *rxa_m[IEEE80211_AGGR_BAWMAX]; 161207327Srpaulo void *rxa_private; 162207370Srpaulo uint64_t rxa_pad[3]; 163170530Ssam}; 164170530Ssam 165170530Ssamvoid ieee80211_ht_attach(struct ieee80211com *); 166170530Ssamvoid ieee80211_ht_detach(struct ieee80211com *); 167178354Ssamvoid ieee80211_ht_vattach(struct ieee80211vap *); 168178354Ssamvoid ieee80211_ht_vdetach(struct ieee80211vap *); 169170530Ssam 170170530Ssamvoid ieee80211_ht_announce(struct ieee80211com *); 171170530Ssam 172178354Ssamstruct ieee80211_mcs_rates { 173178354Ssam uint16_t ht20_rate_800ns; 174178354Ssam uint16_t ht20_rate_400ns; 175178354Ssam uint16_t ht40_rate_800ns; 176178354Ssam uint16_t ht40_rate_400ns; 177178354Ssam}; 178219456Sbschmidtextern const struct ieee80211_mcs_rates ieee80211_htrates[]; 179170530Ssamconst struct ieee80211_htrateset *ieee80211_get_suphtrates( 180170530Ssam struct ieee80211com *, const struct ieee80211_channel *); 181170530Ssam 182170530Ssamstruct ieee80211_node; 183170530Ssamint ieee80211_setup_htrates(struct ieee80211_node *, 184170530Ssam const uint8_t *htcap, int flags); 185170530Ssamvoid ieee80211_setup_basic_htrates(struct ieee80211_node *, 186170530Ssam const uint8_t *htinfo); 187170530Ssamstruct mbuf *ieee80211_decap_amsdu(struct ieee80211_node *, struct mbuf *); 188170530Ssamint ieee80211_ampdu_reorder(struct ieee80211_node *, struct mbuf *); 189170530Ssamvoid ieee80211_recv_bar(struct ieee80211_node *, struct mbuf *); 190183254Ssamvoid ieee80211_ht_node_init(struct ieee80211_node *); 191170530Ssamvoid ieee80211_ht_node_cleanup(struct ieee80211_node *); 192178354Ssamvoid ieee80211_ht_node_age(struct ieee80211_node *); 193178354Ssam 194173273Ssamstruct ieee80211_channel *ieee80211_ht_adjust_channel(struct ieee80211com *, 195173273Ssam struct ieee80211_channel *, int); 196173273Ssamvoid ieee80211_ht_wds_init(struct ieee80211_node *); 197173273Ssamvoid ieee80211_ht_node_join(struct ieee80211_node *); 198173273Ssamvoid ieee80211_ht_node_leave(struct ieee80211_node *); 199178354Ssamvoid ieee80211_htprot_update(struct ieee80211com *, int protmode); 200173273Ssamvoid ieee80211_ht_timeout(struct ieee80211com *); 201170530Ssamvoid ieee80211_parse_htcap(struct ieee80211_node *, const uint8_t *); 202170530Ssamvoid ieee80211_parse_htinfo(struct ieee80211_node *, const uint8_t *); 203233452Sadrianint ieee80211_ht_updateparams(struct ieee80211_node *, const uint8_t *, 204183254Ssam const uint8_t *); 205183254Ssamvoid ieee80211_ht_updatehtcap(struct ieee80211_node *, const uint8_t *); 206170530Ssamint ieee80211_ampdu_request(struct ieee80211_node *, 207170530Ssam struct ieee80211_tx_ampdu *); 208173273Ssamvoid ieee80211_ampdu_stop(struct ieee80211_node *, 209183250Ssam struct ieee80211_tx_ampdu *, int); 210184280Ssamint ieee80211_send_bar(struct ieee80211_node *, struct ieee80211_tx_ampdu *, 211184280Ssam ieee80211_seq); 212170530Ssamuint8_t *ieee80211_add_htcap(uint8_t *, struct ieee80211_node *); 213330457Seadleruint8_t *ieee80211_add_htcap_ch(uint8_t *, struct ieee80211vap *, 214330457Seadler struct ieee80211_channel *); 215170530Ssamuint8_t *ieee80211_add_htcap_vendor(uint8_t *, struct ieee80211_node *); 216170530Ssamuint8_t *ieee80211_add_htinfo(uint8_t *, struct ieee80211_node *); 217170530Ssamuint8_t *ieee80211_add_htinfo_vendor(uint8_t *, struct ieee80211_node *); 218172211Ssamstruct ieee80211_beacon_offsets; 219178354Ssamvoid ieee80211_ht_update_beacon(struct ieee80211vap *, 220172211Ssam struct ieee80211_beacon_offsets *); 221287948Sadrianint ieee80211_ampdu_rx_start_ext(struct ieee80211_node *ni, int tid, 222287948Sadrian int seq, int baw); 223288085Sadrianint ieee80211_ampdu_tx_request_ext(struct ieee80211_node *ni, int tid); 224288085Sadrianint ieee80211_ampdu_tx_request_active_ext(struct ieee80211_node *ni, 225288085Sadrian int tid, int status); 226287948Sadrian 227170530Ssam#endif /* _NET80211_IEEE80211_HT_H_ */ 228