#ifndef _NET80211_IEEE80211_HT_H_
#define _NET80211_IEEE80211_HT_H_
#include <sys/mbuf.h>
#define IEEE80211_AGGR_BAWMAX 64
#define IEEE80211_NONHT_PRESENT_AGE msecs_to_ticks(60*1000)
struct ieee80211_tx_ampdu {
struct ieee80211_node *txa_ni;
u_short txa_flags;
#define IEEE80211_AGGR_IMMEDIATE 0x0001
#define IEEE80211_AGGR_XCHGPEND 0x0002
#define IEEE80211_AGGR_RUNNING 0x0004
#define IEEE80211_AGGR_SETUP 0x0008
#define IEEE80211_AGGR_NAK 0x0010
#define IEEE80211_AGGR_BARPEND 0x0020
#define IEEE80211_AGGR_WAITRX 0x0040
#define IEEE80211_AGGR_AMSDU 0x0080
uint8_t txa_tid;
uint8_t txa_token;
int txa_lastsample;
int txa_pkts;
int txa_avgpps;
int txa_qbytes;
short txa_qframes;
ieee80211_seq txa_start;
ieee80211_seq txa_seqpending;
uint16_t txa_wnd;
uint8_t txa_attempts;
int txa_nextrequest;
struct callout txa_timer;
void *txa_private;
uint64_t txa_pad[4];
};
#define IEEE80211_AMPDU_RUNNING(tap) \
(((tap)->txa_flags & IEEE80211_AGGR_RUNNING) != 0)
#define IEEE80211_AMPDU_RUNNING_AMSDU(tap) \
(((tap)->txa_flags & (IEEE80211_AGGR_RUNNING | IEEE80211_AGGR_AMSDU)) \
== (IEEE80211_AGGR_RUNNING | IEEE80211_AGGR_AMSDU))
#define IEEE80211_AMPDU_NACKED(tap)\
(!! ((tap)->txa_flags & IEEE80211_AGGR_NAK))
#define IEEE80211_AMPDU_REQUESTED(tap) \
(((tap)->txa_flags & \
(IEEE80211_AGGR_RUNNING|IEEE80211_AGGR_XCHGPEND|IEEE80211_AGGR_NAK)) != 0)
#define IEEE80211_AGGR_BITS \
"\20\1IMMEDIATE\2XCHGPEND\3RUNNING\4SETUP\5NAK" \
"\6BARPEND\7WAITRX\10AMSDU"
static __inline void
ieee80211_txampdu_init_pps(struct ieee80211_tx_ampdu *tap)
{
tap->txa_lastsample = ticks;
tap->txa_avgpps = 0;
}
static __inline void
ieee80211_txampdu_update_pps(struct ieee80211_tx_ampdu *tap)
{
tap->txa_avgpps = ((tap->txa_avgpps << 2) -
tap->txa_avgpps + tap->txa_pkts) >> 2;
}
static __inline void
ieee80211_txampdu_count_packet(struct ieee80211_tx_ampdu *tap)
{
while (ticks - tap->txa_lastsample >= hz) {
ieee80211_txampdu_update_pps(tap);
tap->txa_pkts = 0;
if (tap->txa_avgpps == 0) {
tap->txa_lastsample = ticks;
break;
}
tap->txa_lastsample += hz;
}
tap->txa_pkts++;
}
static __inline int
ieee80211_txampdu_getpps(struct ieee80211_tx_ampdu *tap)
{
while (ticks - tap->txa_lastsample >= hz) {
ieee80211_txampdu_update_pps(tap);
tap->txa_pkts = 0;
if (tap->txa_avgpps == 0) {
tap->txa_lastsample = ticks;
break;
}
tap->txa_lastsample += hz;
}
return tap->txa_avgpps;
}
struct ieee80211_rx_ampdu {
int rxa_flags;
int rxa_qbytes;
short rxa_qframes;
ieee80211_seq rxa_seqstart;
ieee80211_seq rxa_start;
uint16_t rxa_wnd;
int rxa_age;
int rxa_nframes;
struct mbufq rxa_mq[IEEE80211_AGGR_BAWMAX];
void *rxa_private;
uint64_t rxa_pad[3];
};
void ieee80211_ht_attach(struct ieee80211com *);
void ieee80211_ht_detach(struct ieee80211com *);
void ieee80211_ht_vattach(struct ieee80211vap *);
void ieee80211_ht_vdetach(struct ieee80211vap *);
void ieee80211_ht_announce(struct ieee80211com *);
struct ieee80211_mcs_rates {
uint16_t ht20_rate_800ns;
uint16_t ht20_rate_400ns;
uint16_t ht40_rate_800ns;
uint16_t ht40_rate_400ns;
};
extern const struct ieee80211_mcs_rates ieee80211_htrates[];
void ieee80211_init_suphtrates(struct ieee80211com *);
struct ieee80211_node;
int ieee80211_setup_htrates(struct ieee80211_node *,
const uint8_t *htcap, int flags);
void ieee80211_setup_basic_htrates(struct ieee80211_node *,
const uint8_t *htinfo);
struct mbuf *ieee80211_decap_amsdu(struct ieee80211_node *, struct mbuf *);
int ieee80211_ampdu_reorder(struct ieee80211_node *, struct mbuf *,
const struct ieee80211_rx_stats *);
void ieee80211_recv_bar(struct ieee80211_node *, struct mbuf *);
void ieee80211_ht_node_init(struct ieee80211_node *);
void ieee80211_ht_node_cleanup(struct ieee80211_node *);
void ieee80211_ht_node_age(struct ieee80211_node *);
struct ieee80211_channel *ieee80211_ht_adjust_channel(struct ieee80211com *,
struct ieee80211_channel *, int);
void ieee80211_ht_wds_init(struct ieee80211_node *);
void ieee80211_ht_node_join(struct ieee80211_node *);
void ieee80211_ht_node_leave(struct ieee80211_node *);
void ieee80211_htprot_update(struct ieee80211vap *, int protmode);
void ieee80211_ht_timeout(struct ieee80211vap *);
void ieee80211_parse_htcap(struct ieee80211_node *, const uint8_t *);
void ieee80211_parse_htinfo(struct ieee80211_node *, const uint8_t *);
void ieee80211_ht_updateparams(struct ieee80211_node *, const uint8_t *,
const uint8_t *);
int ieee80211_ht_updateparams_final(struct ieee80211_node *,
const uint8_t *, const uint8_t *);
void ieee80211_ht_updatehtcap(struct ieee80211_node *, const uint8_t *);
void ieee80211_ht_updatehtcap_final(struct ieee80211_node *);
int ieee80211_ampdu_request(struct ieee80211_node *,
struct ieee80211_tx_ampdu *);
void ieee80211_ampdu_stop(struct ieee80211_node *,
struct ieee80211_tx_ampdu *, int);
int ieee80211_send_bar(struct ieee80211_node *, struct ieee80211_tx_ampdu *,
ieee80211_seq);
uint8_t *ieee80211_add_htcap(uint8_t *, struct ieee80211_node *);
uint8_t *ieee80211_add_htcap_ch(uint8_t *, struct ieee80211vap *,
struct ieee80211_channel *);
uint8_t *ieee80211_add_htcap_vendor(uint8_t *, struct ieee80211_node *);
uint8_t *ieee80211_add_htinfo(uint8_t *, struct ieee80211_node *);
uint8_t *ieee80211_add_htinfo_vendor(uint8_t *, struct ieee80211_node *);
struct ieee80211_beacon_offsets;
void ieee80211_ht_update_beacon(struct ieee80211vap *,
struct ieee80211_beacon_offsets *);
int ieee80211_ampdu_rx_start_ext(struct ieee80211_node *ni, int tid,
int seq, int baw);
void ieee80211_ampdu_rx_stop_ext(struct ieee80211_node *ni, int tid);
int ieee80211_ampdu_tx_request_ext(struct ieee80211_node *ni, int tid);
int ieee80211_ampdu_tx_request_active_ext(struct ieee80211_node *ni,
int tid, int status);
void ieee80211_htinfo_notify(struct ieee80211vap *vap);
int ieee80211_ht_get_node_ampdu_density(const struct ieee80211_node *ni);
int ieee80211_ht_get_node_ampdu_limit(const struct ieee80211_node *ni);
bool ieee80211_ht_check_tx_shortgi_20(const struct ieee80211_node *ni);
bool ieee80211_ht_check_tx_shortgi_40(const struct ieee80211_node *ni);
bool ieee80211_ht_check_tx_ht40(const struct ieee80211_node *ni);
bool ieee80211_ht_check_tx_ht(const struct ieee80211_node *ht);
#endif