| 1 | /*- |
| 2 | * SPDX-License-Identifier: BSD-2-Clause |
| 3 | * |
| 4 | * Copyright (c) 2001 Atsushi Onoe |
| 5 | * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting |
| 6 | * All rights reserved. |
| 7 | * |
| 8 | * Redistribution and use in source and binary forms, with or without |
| 9 | * modification, are permitted provided that the following conditions |
| 10 | * are met: |
| 11 | * 1. Redistributions of source code must retain the above copyright |
| 12 | * notice, this list of conditions and the following disclaimer. |
| 13 | * 2. Redistributions in binary form must reproduce the above copyright |
| 14 | * notice, this list of conditions and the following disclaimer in the |
| 15 | * documentation and/or other materials provided with the distribution. |
| 16 | * |
| 17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
| 18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
| 19 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
| 20 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
| 21 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
| 22 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 23 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 24 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
| 26 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 27 | */ |
| 28 | #ifndef _NET80211_IEEE80211_NODE_H_ |
| 29 | #define _NET80211_IEEE80211_NODE_H_ |
| 30 | |
| 31 | #include <net80211/ieee80211_ioctl.h>		/* for ieee80211_nodestats */ |
| 32 | #include <net80211/ieee80211_ht.h>		/* for aggregation state */ |
| 33 | |
| 34 | /* |
| 35 | * Each ieee80211com instance has a single timer that fires every |
| 36 | * IEEE80211_INACT_WAIT seconds to handle "inactivity processing". |
| 37 | * This is used to do node inactivity processing when operating |
| 38 | * as an AP, adhoc or mesh mode. For inactivity processing each node |
| 39 | * has a timeout set in its ni_inact field that is decremented |
| 40 | * on each timeout and the node is reclaimed when the counter goes |
| 41 | * to zero. We use different inactivity timeout values depending |
| 42 | * on whether the node is associated and authorized (either by |
| 43 | * 802.1x or open/shared key authentication) or associated but yet |
| 44 | * to be authorized. The latter timeout is shorter to more aggressively |
| 45 | * reclaim nodes that leave part way through the 802.1x exchange. |
| 46 | */ |
| 47 | #define	IEEE80211_INACT_WAIT	15		/* inactivity interval (secs) */ |
| 48 | #define	IEEE80211_INACT_INIT	(30/IEEE80211_INACT_WAIT)	/* initial */ |
| 49 | #define	IEEE80211_INACT_AUTH	(180/IEEE80211_INACT_WAIT)	/* associated but not authorized */ |
| 50 | #define	IEEE80211_INACT_RUN	(300/IEEE80211_INACT_WAIT)	/* authorized */ |
| 51 | #define	IEEE80211_INACT_PROBE	(30/IEEE80211_INACT_WAIT)	/* probe */ |
| 52 | #define	IEEE80211_INACT_SCAN	(300/IEEE80211_INACT_WAIT)	/* scanned */ |
| 53 | |
| 54 | #define	IEEE80211_TRANS_WAIT 	2		/* mgt frame tx timer (secs) */ |
| 55 | |
| 56 | /* threshold for aging overlapping non-ERP bss */ |
| 57 | #define	IEEE80211_NONERP_PRESENT_AGE	msecs_to_ticks(60*1000) |
| 58 | |
| 59 | #define	IEEE80211_NODE_HASHSIZE	32		/* NB: hash size must be pow2 */ |
| 60 | /* simple hash is enough for variation of macaddr */ |
| 61 | #define	IEEE80211_NODE_HASH(ic, addr)	\ |
| 62 | 	(((const uint8_t *)(addr))[IEEE80211_ADDR_LEN - 1] % \ |
| 63 | 		IEEE80211_NODE_HASHSIZE) |
| 64 | |
| 65 | struct ieee80211_node_table; |
| 66 | struct ieee80211com; |
| 67 | struct ieee80211vap; |
| 68 | struct ieee80211_scanparams; |
| 69 | |
| 70 | /* |
| 71 | * Information element (IE) ``blob''. We use this structure |
| 72 | * to capture management frame payloads that need to be |
| 73 | * retained. Information elements within the payload that |
| 74 | * we need to consult have references recorded. |
| 75 | */ |
| 76 | struct ieee80211_ies { |
| 77 | 	/* the following are either NULL or point within data */ |
| 78 | 	uint8_t	*wpa_ie;	/* captured WPA ie */ |
| 79 | 	uint8_t	*rsn_ie;	/* captured RSN ie */ |
| 80 | 	uint8_t	*wme_ie;	/* captured WME ie */ |
| 81 | 	uint8_t	*ath_ie;	/* captured Atheros ie */ |
| 82 | 	uint8_t	*htcap_ie;	/* captured HTCAP ie */ |
| 83 | 	uint8_t	*htinfo_ie;	/* captured HTINFO ie */ |
| 84 | 	uint8_t	*tdma_ie;	/* captured TDMA ie */ |
| 85 | 	uint8_t *meshid_ie;	/* captured MESH ID ie */ |
| 86 | 	uint8_t	*vhtcap_ie;	/* captured VHTCAP ie */ |
| 87 | 	uint8_t	*vhtopmode_ie;	/* captured VHTOPMODE ie */ |
| 88 | 	uint8_t	*vhtpwrenv_ie;	/* captured VHTPWRENV ie */ |
| 89 | 	uint8_t	*apchanrep_ie;	/* captured APCHANREP ie */ |
| 90 | 	uint8_t	*bssload_ie;	/* captured BSSLOAD ie */ |
| 91 | 	uint8_t	*spare[4]; |
| 92 | 	/* NB: these must be the last members of this structure */ |
| 93 | 	uint8_t	*data;		/* frame data > 802.11 header */ |
| 94 | 	int	len;		/* data size in bytes */ |
| 95 | }; |
| 96 | |
| 97 | /* |
| 98 | * 802.11s (Mesh) Peer Link FSM state. |
| 99 | */ |
| 100 | enum ieee80211_mesh_mlstate { |
| 101 | 	IEEE80211_NODE_MESH_IDLE	= 0, |
| 102 | 	IEEE80211_NODE_MESH_OPENSNT	= 1,	/* open frame sent */ |
| 103 | 	IEEE80211_NODE_MESH_OPENRCV	= 2,	/* open frame received */ |
| 104 | 	IEEE80211_NODE_MESH_CONFIRMRCV	= 3,	/* confirm frame received */ |
| 105 | 	IEEE80211_NODE_MESH_ESTABLISHED	= 4,	/* link established */ |
| 106 | 	IEEE80211_NODE_MESH_HOLDING	= 5,	/* link closing */ |
| 107 | }; |
| 108 | #define	IEEE80211_MESH_MLSTATE_BITS \ |
| 109 | 	"\20\1IDLE\2OPENSNT\2OPENRCV\3CONFIRMRCV\4ESTABLISHED\5HOLDING" |
| 110 | |
| 111 | /* |
| 112 | * This enum was shared with the LinuxKPI enum ieee80211_sta_rx_bandwidth |
| 113 | * describing up-to which channel width the station can receive. |
| 114 | * Rather than using hardcoded MHz values for the channel width use an enum with |
| 115 | * flags. This allows us to keep the uint8_t slot for ni_chw in |
| 116 | * struct ieee80211_node it means we do not have to sync to the value for |
| 117 | * LinuxKPI (just the names). |
| 118 | * |
| 119 | * NB: BW_20 needs to 0 and values need to be sorted! Cannot make it |
| 120 | * bitfield-alike for use with %b. |
| 121 | */ |
| 122 | enum net80211_sta_rx_bw { |
| 123 | 	NET80211_STA_RX_BW_20		= 0x00, |
| 124 | 	NET80211_STA_RX_BW_40, |
| 125 | 	NET80211_STA_RX_BW_80, |
| 126 | 	NET80211_STA_RX_BW_160, |
| 127 | 	NET80211_STA_RX_BW_320, |
| 128 | } __packed; |
| 129 | |
| 130 | static inline const char * |
| 131 | net80211_ni_chw_to_str(enum net80211_sta_rx_bw bw) |
| 132 | { |
| 133 | 	switch (bw) { |
| 134 | 	case NET80211_STA_RX_BW_20:	return ("BW_20"); |
| 135 | 	case NET80211_STA_RX_BW_40:	return ("BW_40"); |
| 136 | 	case NET80211_STA_RX_BW_80:	return ("BW_80"); |
| 137 | 	case NET80211_STA_RX_BW_160:	return ("BW_160"); |
| 138 | 	case NET80211_STA_RX_BW_320:	return ("BW_320"); |
| 139 | 	} |
| 140 | } |
| 141 | |
| 142 | enum ieee80211_node_txrate_type { |
| 143 | 	IEEE80211_NODE_TXRATE_UNDEFINED		= 0, |
| 144 | 	IEEE80211_NODE_TXRATE_LEGACY		= 1, /* CCK/OFDM, HT for now */ |
| 145 | 	IEEE80211_NODE_TXRATE_HT		= 2, /* HT */ |
| 146 | 	IEEE80211_NODE_TXRATE_VHT		= 3, /* VHT */ |
| 147 | }; |
| 148 | |
| 149 | struct ieee80211_node_txrate { |
| 150 | 	enum ieee80211_node_txrate_type type; |
| 151 | 	uint8_t		nss;		/* VHT - number of spatial streams */ |
| 152 | 	uint8_t		mcs;		/* HT/VHT - MCS */ |
| 153 | 	uint8_t		dot11rate;	/* Legacy/HT - dot11rate / ratecode */ |
| 154 | }; |
| 155 | |
| 156 | #define	IEEE80211_NODE_TXRATE_INIT_LEGACY(rate) \ |
| 157 | 	(struct ieee80211_node_txrate) { .type = IEEE80211_NODE_TXRATE_LEGACY, \ |
| 158 | 	 .nss = 0, \ |
| 159 | 	 .mcs = 0, \ |
| 160 | 	 .dot11rate = (rate) } |
| 161 | |
| 162 | #define	IEEE80211_NODE_TXRATE_INIT_HT(i_mcs) \ |
| 163 | 	(struct ieee80211_node_txrate) { .type = IEEE80211_NODE_TXRATE_HT, \ |
| 164 | 	 .nss = 0, \ |
| 165 | 	 .mcs = (i_mcs), \ |
| 166 | 	 .dot11rate = (i_mcs) | IEEE80211_RATE_MCS } |
| 167 | |
| 168 | #define	IEEE80211_NODE_TXRATE_INIT_VHT(i_nss, i_mcs) \ |
| 169 | 	(struct ieee80211_node_txrate) { .type = IEEE80211_NODE_TXRATE_VHT, \ |
| 170 | 	 .nss = (i_nss), \ |
| 171 | 	 .mcs = (i_mcs), \ |
| 172 | 	 .dot11rate = 0 } |
| 173 | |
| 174 | /* |
| 175 | * Node specific information. Note that drivers are expected |
| 176 | * to derive from this structure to add device-specific per-node |
| 177 | * state. This is done by overriding the ic_node_* methods in |
| 178 | * the ieee80211com structure. |
| 179 | */ |
| 180 | struct ieee80211_node { |
| 181 | 	struct ieee80211vap	*ni_vap;	/* associated vap */ |
| 182 | 	struct ieee80211com	*ni_ic;		/* copy from vap to save deref*/ |
| 183 | 	struct ieee80211_node_table *ni_table;	/* NB: may be NULL */ |
| 184 | 	TAILQ_ENTRY(ieee80211_node) ni_list;	/* list of all nodes */ |
| 185 | 	LIST_ENTRY(ieee80211_node) ni_hash;	/* hash collision list */ |
| 186 | 	u_int			ni_refcnt;	/* count of held references */ |
| 187 | 	u_int			ni_flags; |
| 188 | #define	IEEE80211_NODE_AUTH	0x000001	/* authorized for data */ |
| 189 | #define	IEEE80211_NODE_QOS	0x000002	/* QoS enabled */ |
| 190 | #define	IEEE80211_NODE_ERP	0x000004	/* ERP enabled */ |
| 191 | /* NB: this must have the same value as IEEE80211_FC1_PWR_MGT */ |
| 192 | #define	IEEE80211_NODE_PWR_MGT	0x000010	/* power save mode enabled */ |
| 193 | #define	IEEE80211_NODE_AREF	0x000020	/* authentication ref held */ |
| 194 | #define	IEEE80211_NODE_HT	0x000040	/* HT enabled */ |
| 195 | #define	IEEE80211_NODE_HTCOMPAT	0x000080	/* HT setup w/ vendor OUI's */ |
| 196 | #define	IEEE80211_NODE_WPS	0x000100	/* WPS association */ |
| 197 | #define	IEEE80211_NODE_TSN	0x000200	/* TSN association */ |
| 198 | #define	IEEE80211_NODE_AMPDU_RX	0x000400	/* AMPDU rx enabled */ |
| 199 | #define	IEEE80211_NODE_AMPDU_TX	0x000800	/* AMPDU tx enabled */ |
| 200 | #define	IEEE80211_NODE_MIMO_PS	0x001000	/* MIMO power save enabled */ |
| 201 | #define	IEEE80211_NODE_MIMO_RTS	0x002000	/* send RTS in MIMO PS */ |
| 202 | #define	IEEE80211_NODE_RIFS	0x004000	/* RIFS enabled */ |
| 203 | #define	IEEE80211_NODE_SGI20	0x008000	/* Short GI in HT20 enabled */ |
| 204 | #define	IEEE80211_NODE_SGI40	0x010000	/* Short GI in HT40 enabled */ |
| 205 | #define	IEEE80211_NODE_ASSOCID	0x020000	/* xmit requires associd */ |
| 206 | #define	IEEE80211_NODE_AMSDU_RX	0x040000	/* AMSDU rx enabled */ |
| 207 | #define	IEEE80211_NODE_AMSDU_TX	0x080000	/* AMSDU tx enabled */ |
| 208 | #define	IEEE80211_NODE_VHT	0x100000	/* VHT enabled */ |
| 209 | #define	IEEE80211_NODE_LDPC	0x200000	/* LDPC enabled */ |
| 210 | #define	IEEE80211_NODE_UAPSD	0x400000	/* U-APSD power save enabled */ |
| 211 | 	uint16_t		ni_associd;	/* association ID */ |
| 212 | 	uint16_t		ni_vlan;	/* vlan tag */ |
| 213 | 	uint16_t		ni_txpower;	/* current transmit power */ |
| 214 | 	uint8_t			ni_authmode;	/* authentication algorithm */ |
| 215 | 	uint8_t			ni_ath_flags;	/* Atheros feature flags */ |
| 216 | 	/* NB: These must have the same values as IEEE80211_ATHC_* */ |
| 217 | #define IEEE80211_NODE_TURBOP	0x0001		/* Turbo prime enable */ |
| 218 | #define IEEE80211_NODE_COMP	0x0002		/* Compresssion enable */ |
| 219 | #define IEEE80211_NODE_FF	0x0004 /* Fast Frame capable */ |
| 220 | #define IEEE80211_NODE_XR	0x0008		/* Atheros WME enable */ |
| 221 | #define IEEE80211_NODE_AR	0x0010		/* AR capable */ |
| 222 | #define IEEE80211_NODE_BOOST	0x0080		/* Dynamic Turbo boosted */ |
| 223 | 	uint16_t		ni_ath_defkeyix;/* Atheros def key index */ |
| 224 | 	const struct ieee80211_txparam *ni_txparms; |
| 225 | 	uint32_t		ni_jointime;	/* time of join (secs) */ |
| 226 | 	uint32_t		*ni_challenge;	/* shared-key challenge */ |
| 227 | 	struct ieee80211_ies	ni_ies;		/* captured ie's */ |
| 228 | 						/* tx seq per-tid */ |
| 229 | 	ieee80211_seq		ni_txseqs[IEEE80211_TID_SIZE]; |
| 230 | 						/* rx seq previous per-tid*/ |
| 231 | 	ieee80211_seq		ni_rxseqs[IEEE80211_TID_SIZE]; |
| 232 | 	uint32_t		ni_rxfragstamp;	/* time stamp of last rx frag */ |
| 233 | 	struct mbuf		*ni_rxfrag[3];	/* rx frag reassembly */ |
| 234 | 	struct ieee80211_key	ni_ucastkey;	/* unicast key */ |
| 235 | |
| 236 | 	/* hardware */ |
| 237 | 	uint32_t		ni_avgrssi;	/* recv ssi state */ |
| 238 | 	int8_t			ni_noise;	/* noise floor */ |
| 239 | |
| 240 | 	/* mimo statistics */ |
| 241 | 	uint32_t		ni_mimo_rssi_ctl[IEEE80211_MAX_CHAINS]; |
| 242 | 	uint32_t		ni_mimo_rssi_ext[IEEE80211_MAX_CHAINS]; |
| 243 | 	uint8_t			ni_mimo_noise_ctl[IEEE80211_MAX_CHAINS]; |
| 244 | 	uint8_t			ni_mimo_noise_ext[IEEE80211_MAX_CHAINS]; |
| 245 | 	uint8_t			ni_mimo_chains; |
| 246 | |
| 247 | 	/* header */ |
| 248 | 	uint8_t			ni_macaddr[IEEE80211_ADDR_LEN]; |
| 249 | 	uint8_t			ni_bssid[IEEE80211_ADDR_LEN]; |
| 250 | |
| 251 | 	/* beacon, probe response */ |
| 252 | 	union { |
| 253 | 		uint8_t		data[8]; |
| 254 | 		u_int64_t	tsf; |
| 255 | 	} ni_tstamp;				/* from last rcv'd beacon */ |
| 256 | 	uint16_t		ni_intval;	/* beacon interval */ |
| 257 | 	uint16_t		ni_capinfo;	/* capabilities */ |
| 258 | 	uint8_t			ni_esslen; |
| 259 | 	uint8_t			ni_essid[IEEE80211_NWID_LEN]; |
| 260 | 	struct ieee80211_rateset ni_rates;	/* negotiated rate set */ |
| 261 | 	struct ieee80211_channel *ni_chan; |
| 262 | 	uint16_t		ni_fhdwell;	/* FH only */ |
| 263 | 	uint8_t			ni_fhindex;	/* FH only */ |
| 264 | 	uint16_t		ni_erp;		/* ERP from beacon/probe resp */ |
| 265 | 	uint16_t		ni_timoff;	/* byte offset to TIM ie */ |
| 266 | 	uint8_t			ni_dtim_period;	/* DTIM period */ |
| 267 | 	uint8_t			ni_dtim_count;	/* DTIM count for last bcn */ |
| 268 | |
| 269 | 	/* 11s state */ |
| 270 | 	uint8_t			ni_meshidlen; |
| 271 | 	uint8_t			ni_meshid[IEEE80211_MESHID_LEN]; |
| 272 | 	enum ieee80211_mesh_mlstate ni_mlstate;	/* peering management state */ |
| 273 | 	uint16_t		ni_mllid;	/* link local ID */ |
| 274 | 	uint16_t		ni_mlpid;	/* link peer ID */ |
| 275 | 	struct callout		ni_mltimer;	/* link mesh timer */ |
| 276 | 	uint8_t			ni_mlrcnt;	/* link mesh retry counter */ |
| 277 | 	uint8_t			ni_mltval;	/* link mesh timer value */ |
| 278 | 	struct callout		ni_mlhtimer;	/* link mesh backoff timer */ |
| 279 | 	uint8_t			ni_mlhcnt;	/* link mesh holding counter */ |
| 280 | |
| 281 | 	/* 11n state */ |
| 282 | 	uint16_t		ni_htcap;	/* HT capabilities */ |
| 283 | 	uint8_t			ni_htparam;	/* HT params */ |
| 284 | 	uint8_t			ni_htctlchan;	/* HT control channel */ |
| 285 | 	uint8_t			ni_ht2ndchan;	/* HT 2nd channel */ |
| 286 | 	uint8_t			ni_htopmode;	/* HT operating mode */ |
| 287 | 	uint8_t			ni_htstbc;	/* HT */ |
| 288 | 	enum net80211_sta_rx_bw ni_chw;	/* negotiated channel width */ |
| 289 | 	struct ieee80211_htrateset ni_htrates;	/* negotiated ht rate set */ |
| 290 | 	struct ieee80211_tx_ampdu ni_tx_ampdu[WME_NUM_TID]; |
| 291 | 	struct ieee80211_rx_ampdu ni_rx_ampdu[WME_NUM_TID]; |
| 292 | |
| 293 | 	/* VHT state */ |
| 294 | 	uint32_t		ni_vhtcap; |
| 295 | 	uint16_t		ni_vht_basicmcs;	/* Basic VHT MCS bitmap from IE */ |
| 296 | 	uint16_t		ni_vht_tx_map;		/* Negotiated MCS TX map with peer */ |
| 297 | 	struct ieee80211_vht_mcs_info	ni_vht_mcsinfo; |
| 298 | 	uint8_t			ni_vht_chan1;	/* 20/40/80/160 - VHT chan1 */ |
| 299 | 	uint8_t			ni_vht_chan2;	/* 80+80 - VHT chan2 */ |
| 300 | 	uint8_t			ni_vht_chanwidth;	/* IEEE80211_VHT_CHANWIDTH_ */ |
| 301 | 	uint8_t			ni_vht_pad1; |
| 302 | 	uint32_t		ni_vht_spare[8]; |
| 303 | |
| 304 | 	/* fast-frames state */ |
| 305 | 	struct mbuf *		ni_tx_superg[WME_NUM_TID]; |
| 306 | |
| 307 | 	/* others */ |
| 308 | 	short			ni_inact;	/* inactivity mark count */ |
| 309 | 	short			ni_inact_reload;/* inactivity reload value */ |
| 310 | 	struct ieee80211_node_txrate	ni_txrate;	/* current transmit rate */ |
| 311 | 	struct ieee80211_psq	ni_psq;		/* power save queue */ |
| 312 | 	struct ieee80211_nodestats ni_stats;	/* per-node statistics */ |
| 313 | |
| 314 | 	struct ieee80211vap	*ni_wdsvap;	/* associated WDS vap */ |
| 315 | 	void			*ni_rctls;	/* private ratectl state */ |
| 316 | |
| 317 | 	/* quiet time IE state for the given node */ |
| 318 | 	uint32_t		ni_quiet_ie_set;	/* Quiet time IE was seen */ |
| 319 | 	struct			ieee80211_quiet_ie ni_quiet_ie;	/* last seen quiet IE */ |
| 320 | |
| 321 | 	/* U-APSD */ |
| 322 | 	uint8_t			ni_uapsd;	/* U-APSD per-node flags matching WMM STA QoS Info field */ |
| 323 | |
| 324 | 	void			*ni_drv_data;	/* driver specific */ |
| 325 | |
| 326 | 	uint64_t		ni_spare[3]; |
| 327 | }; |
| 328 | MALLOC_DECLARE(M_80211_NODE); |
| 329 | MALLOC_DECLARE(M_80211_NODE_IE); |
| 330 | |
| 331 | #define	IEEE80211_NODE_ATH	(IEEE80211_NODE_FF | IEEE80211_NODE_TURBOP) |
| 332 | #define	IEEE80211_NODE_AMPDU \ |
| 333 | 	(IEEE80211_NODE_AMPDU_RX | IEEE80211_NODE_AMPDU_TX) |
| 334 | #define	IEEE80211_NODE_AMSDU \ |
| 335 | 	(IEEE80211_NODE_AMSDU_RX | IEEE80211_NODE_AMSDU_TX) |
| 336 | #define	IEEE80211_NODE_HT_ALL \ |
| 337 | 	(IEEE80211_NODE_HT | IEEE80211_NODE_HTCOMPAT | \ |
| 338 | 	 IEEE80211_NODE_AMPDU | IEEE80211_NODE_AMSDU | \ |
| 339 | 	 IEEE80211_NODE_MIMO_PS | IEEE80211_NODE_MIMO_RTS | \ |
| 340 | 	 IEEE80211_NODE_RIFS | IEEE80211_NODE_SGI20 | IEEE80211_NODE_SGI40) |
| 341 | |
| 342 | #define	IEEE80211_NODE_BITS \ |
| 343 | 	"\20\1AUTH\2QOS\3ERP\5PWR_MGT\6AREF\7HT\10HTCOMPAT\11WPS\12TSN" \ |
| 344 | 	"\13AMPDU_RX\14AMPDU_TX\15MIMO_PS\16MIMO_RTS\17RIFS\20SGI20\21SGI40" \ |
| 345 | 	"\22ASSOCID\23AMSDU_RX\24AMSDU_TX\25VHT\26LDPC\27UAPSD" |
| 346 | |
| 347 | #define	IEEE80211_NODE_AID(ni)	IEEE80211_AID(ni->ni_associd) |
| 348 | |
| 349 | #define	IEEE80211_NODE_STAT(ni,stat)	(ni->ni_stats.ns_##stat++) |
| 350 | #define	IEEE80211_NODE_STAT_ADD(ni,stat,v)	(ni->ni_stats.ns_##stat += v) |
| 351 | #define	IEEE80211_NODE_STAT_SET(ni,stat,v)	(ni->ni_stats.ns_##stat = v) |
| 352 | |
| 353 | /* |
| 354 | * Filtered rssi calculation support. The receive rssi is maintained |
| 355 | * as an average over the last 10 frames received using a low pass filter |
| 356 | * (all frames for now, possibly need to be more selective). Calculations |
| 357 | * are designed such that a good compiler can optimize them. The avg |
| 358 | * rssi state should be initialized to IEEE80211_RSSI_DUMMY_MARKER and |
| 359 | * each sample incorporated with IEEE80211_RSSI_LPF. Use IEEE80211_RSSI_GET |
| 360 | * to extract the current value. |
| 361 | * |
| 362 | * Note that we assume rssi data are in the range [-127..127] and we |
| 363 | * discard values <-20. This is consistent with assumptions throughout |
| 364 | * net80211 that signal strength data are in .5 dBm units relative to |
| 365 | * the current noise floor (linear, not log). |
| 366 | */ |
| 367 | #define IEEE80211_RSSI_LPF_LEN		10 |
| 368 | #define	IEEE80211_RSSI_DUMMY_MARKER	127 |
| 369 | /* NB: pow2 to optimize out * and / */ |
| 370 | #define	IEEE80211_RSSI_EP_MULTIPLIER	(1<<7) |
| 371 | #define IEEE80211_RSSI_IN(x)		((x) * IEEE80211_RSSI_EP_MULTIPLIER) |
| 372 | #define _IEEE80211_RSSI_LPF(x, y, len) \ |
| 373 | (((x) != IEEE80211_RSSI_DUMMY_MARKER) ? (((x) * ((len) - 1) + (y)) / (len)) : (y)) |
| 374 | #define IEEE80211_RSSI_LPF(x, y) do {					\ |
| 375 | if ((y) >= -20) {							\ |
| 376 | 	x = _IEEE80211_RSSI_LPF((x), IEEE80211_RSSI_IN((y)), 		\ |
| 377 | 		IEEE80211_RSSI_LPF_LEN);				\ |
| 378 | }									\ |
| 379 | } while (0) |
| 380 | #define	IEEE80211_RSSI_EP_RND(x, mul) \ |
| 381 | 	((((x) % (mul)) >= ((mul)/2)) ? ((x) + ((mul) - 1)) / (mul) : (x)/(mul)) |
| 382 | #define	IEEE80211_RSSI_GET(x) \ |
| 383 | 	IEEE80211_RSSI_EP_RND(x, IEEE80211_RSSI_EP_MULTIPLIER) |
| 384 | |
| 385 | void	ieee80211_node_attach(struct ieee80211com *); |
| 386 | void	ieee80211_node_lateattach(struct ieee80211com *); |
| 387 | void	ieee80211_node_detach(struct ieee80211com *); |
| 388 | void	ieee80211_node_vattach(struct ieee80211vap *); |
| 389 | void	ieee80211_node_latevattach(struct ieee80211vap *); |
| 390 | void	ieee80211_node_vdetach(struct ieee80211vap *); |
| 391 | |
| 392 | static __inline int |
| 393 | ieee80211_node_is_authorized(const struct ieee80211_node *ni) |
| 394 | { |
| 395 | 	return (ni->ni_flags & IEEE80211_NODE_AUTH); |
| 396 | } |
| 397 | |
| 398 | void	ieee80211_node_authorize(struct ieee80211_node *); |
| 399 | void	ieee80211_node_unauthorize(struct ieee80211_node *); |
| 400 | |
| 401 | void	ieee80211_node_setuptxparms(struct ieee80211_node *); |
| 402 | void	ieee80211_node_set_chan(struct ieee80211_node *, |
| 403 | 		struct ieee80211_channel *); |
| 404 | void	ieee80211_create_ibss(struct ieee80211vap*, struct ieee80211_channel *); |
| 405 | void	ieee80211_reset_bss(struct ieee80211vap *); |
| 406 | void	ieee80211_sync_curchan(struct ieee80211com *); |
| 407 | void	ieee80211_setupcurchan(struct ieee80211com *, |
| 408 | 	 struct ieee80211_channel *); |
| 409 | void	ieee80211_setcurchan(struct ieee80211com *, struct ieee80211_channel *); |
| 410 | void	ieee80211_update_chw(struct ieee80211com *); |
| 411 | int	ieee80211_ibss_merge_check(struct ieee80211_node *); |
| 412 | int	ieee80211_ibss_node_check_new(struct ieee80211_node *ni, |
| 413 | 	 const struct ieee80211_scanparams *); |
| 414 | int	ieee80211_ibss_merge(struct ieee80211_node *); |
| 415 | struct ieee80211_scan_entry; |
| 416 | int	ieee80211_sta_join(struct ieee80211vap *, struct ieee80211_channel *, |
| 417 | 		const struct ieee80211_scan_entry *); |
| 418 | void	ieee80211_sta_leave(struct ieee80211_node *); |
| 419 | void	ieee80211_node_deauth(struct ieee80211_node *, int); |
| 420 | |
| 421 | int	ieee80211_ies_init(struct ieee80211_ies *, const uint8_t *, int); |
| 422 | void	ieee80211_ies_cleanup(struct ieee80211_ies *); |
| 423 | void	ieee80211_ies_expand(struct ieee80211_ies *); |
| 424 | #define	ieee80211_ies_setie(_ies, _ie, _off) do {		\ |
| 425 | 	(_ies)._ie = (_ies).data + (_off);			\ |
| 426 | } while (0) |
| 427 | |
| 428 | /* |
| 429 | * Table of ieee80211_node instances. Each ieee80211com |
| 430 | * has one that holds association stations (when operating |
| 431 | * as an ap) or neighbors (in ibss mode). |
| 432 | * |
| 433 | * XXX embed this in ieee80211com instead of indirect? |
| 434 | */ |
| 435 | struct ieee80211_node_table { |
| 436 | 	struct ieee80211com	*nt_ic;		/* back reference */ |
| 437 | 	ieee80211_node_lock_t	nt_nodelock;	/* on node table */ |
| 438 | 	TAILQ_HEAD(, ieee80211_node) nt_node;	/* information of all nodes */ |
| 439 | 	LIST_HEAD(, ieee80211_node) nt_hash[IEEE80211_NODE_HASHSIZE]; |
| 440 | 	int			nt_count;	/* number of nodes */ |
| 441 | 	struct ieee80211_node	**nt_keyixmap;	/* key ix -> node map */ |
| 442 | 	int			nt_keyixmax;	/* keyixmap size */ |
| 443 | 	const char		*nt_name;	/* table name for debug msgs */ |
| 444 | 	int			nt_inact_init;	/* initial node inact setting */ |
| 445 | }; |
| 446 | |
| 447 | struct ieee80211_node *ieee80211_tmp_node(struct ieee80211vap *, |
| 448 | 		const uint8_t macaddr[IEEE80211_ADDR_LEN]); |
| 449 | struct ieee80211_node *ieee80211_dup_bss(struct ieee80211vap *, |
| 450 | 		const uint8_t macaddr[IEEE80211_ADDR_LEN]); |
| 451 | struct ieee80211_node *ieee80211_node_create_wds(struct ieee80211vap *, |
| 452 | 		const uint8_t bssid[IEEE80211_ADDR_LEN], |
| 453 | 		struct ieee80211_channel *); |
| 454 | |
| 455 | /* These functions are taking __func__, __LINE__ for IEEE80211_DEBUG_REFCNT */ |
| 456 | struct ieee80211_node *_ieee80211_ref_node(struct ieee80211_node *, |
| 457 | 		const char *func, int line); |
| 458 | void	_ieee80211_free_node(struct ieee80211_node *, |
| 459 | 		const char *func, int line); |
| 460 | struct ieee80211_node *_ieee80211_find_node_locked( |
| 461 | 		struct ieee80211_node_table *, |
| 462 | 		const uint8_t macaddr[IEEE80211_ADDR_LEN], |
| 463 | 		const char *func, int line); |
| 464 | struct ieee80211_node *_ieee80211_find_node(struct ieee80211_node_table *, |
| 465 | 		const uint8_t macaddr[IEEE80211_ADDR_LEN], |
| 466 | 		const char *func, int line); |
| 467 | struct ieee80211_node *_ieee80211_find_vap_node_locked( |
| 468 | 		struct ieee80211_node_table *, |
| 469 | 		const struct ieee80211vap *vap, |
| 470 | 		const uint8_t macaddr[IEEE80211_ADDR_LEN], |
| 471 | 		const char *func, int line); |
| 472 | struct ieee80211_node *_ieee80211_find_vap_node( |
| 473 | 		struct ieee80211_node_table *, |
| 474 | 		const struct ieee80211vap *vap, |
| 475 | 		const uint8_t macaddr[IEEE80211_ADDR_LEN], |
| 476 | 		const char *func, int line); |
| 477 | struct ieee80211_node *_ieee80211_find_rxnode(struct ieee80211com *, |
| 478 | 		const struct ieee80211_frame_min *, |
| 479 | 		const char *func, int line); |
| 480 | struct ieee80211_node *_ieee80211_find_rxnode_withkey( |
| 481 | 		struct ieee80211com *, |
| 482 | 		const struct ieee80211_frame_min *, uint16_t keyix, |
| 483 | 		const char *func, int line); |
| 484 | struct ieee80211_node *_ieee80211_find_txnode(struct ieee80211vap *, |
| 485 | 		const uint8_t macaddr[IEEE80211_ADDR_LEN], |
| 486 | 		const char *func, int line); |
| 487 | #define	ieee80211_ref_node(ni) \ |
| 488 | 	_ieee80211_ref_node(ni, __func__, __LINE__) |
| 489 | #define	ieee80211_free_node(ni) \ |
| 490 | 	_ieee80211_free_node(ni, __func__, __LINE__) |
| 491 | #define	ieee80211_find_node_locked(nt, mac) \ |
| 492 | 	_ieee80211_find_node_locked(nt, mac, __func__, __LINE__) |
| 493 | #define	ieee80211_find_node(nt, mac) \ |
| 494 | 	_ieee80211_find_node(nt, mac, __func__, __LINE__) |
| 495 | #define	ieee80211_find_vap_node_locked(nt, vap, mac) \ |
| 496 | 	_ieee80211_find_vap_node_locked(nt, vap, mac, __func__, __LINE__) |
| 497 | #define	ieee80211_find_vap_node(nt, vap, mac) \ |
| 498 | 	_ieee80211_find_vap_node(nt, vap, mac, __func__, __LINE__) |
| 499 | #define	ieee80211_find_rxnode(ic, wh) \ |
| 500 | 	_ieee80211_find_rxnode(ic, wh, __func__, __LINE__) |
| 501 | #define	ieee80211_find_rxnode_withkey(ic, wh, keyix) \ |
| 502 | 	_ieee80211_find_rxnode_withkey(ic, wh, keyix, __func__, __LINE__) |
| 503 | #define	ieee80211_find_txnode(vap, mac) \ |
| 504 | 	_ieee80211_find_txnode(vap, mac, __func__, __LINE__) |
| 505 | |
| 506 | int	ieee80211_node_delucastkey(struct ieee80211_node *); |
| 507 | void	ieee80211_node_timeout(void *arg); |
| 508 | |
| 509 | typedef void ieee80211_iter_func(void *, struct ieee80211_node *); |
| 510 | int	ieee80211_iterate_nodes_vap(struct ieee80211_node_table *, |
| 511 | 		struct ieee80211vap *, ieee80211_iter_func *, void *); |
| 512 | void	ieee80211_iterate_nodes(struct ieee80211_node_table *, |
| 513 | 		ieee80211_iter_func *, void *); |
| 514 | |
| 515 | void	ieee80211_notify_erp_locked(struct ieee80211com *); |
| 516 | void	ieee80211_dump_node(struct ieee80211_node_table *, |
| 517 | 		struct ieee80211_node *); |
| 518 | void	ieee80211_dump_nodes(struct ieee80211_node_table *); |
| 519 | |
| 520 | struct ieee80211_node *ieee80211_fakeup_adhoc_node(struct ieee80211vap *, |
| 521 | 		const uint8_t macaddr[IEEE80211_ADDR_LEN]); |
| 522 | struct ieee80211_scanparams; |
| 523 | void	ieee80211_init_neighbor(struct ieee80211_node *, |
| 524 | 		const struct ieee80211_frame *, |
| 525 | 		const struct ieee80211_scanparams *); |
| 526 | struct ieee80211_node *ieee80211_add_neighbor(struct ieee80211vap *, |
| 527 | 		const struct ieee80211_frame *, |
| 528 | 		const struct ieee80211_scanparams *); |
| 529 | void	ieee80211_node_join(struct ieee80211_node *,int); |
| 530 | void	ieee80211_node_leave(struct ieee80211_node *); |
| 531 | int8_t	ieee80211_getrssi(struct ieee80211vap *); |
| 532 | void	ieee80211_getsignal(struct ieee80211vap *, int8_t *, int8_t *); |
| 533 | |
| 534 | /* TX sequence space related routines */ |
| 535 | ieee80211_seq	ieee80211_tx_seqno_fetch_incr(struct ieee80211_node *, |
| 536 | 	uint8_t); |
| 537 | ieee80211_seq	ieee80211_tx_seqno_fetch(const struct ieee80211_node *, |
| 538 | 	uint8_t); |
| 539 | |
| 540 | /* |
| 541 | * Node transmit rate specific manipulation. |
| 542 | * |
| 543 | * This should eventually be refactored into its own type. |
| 544 | */ |
| 545 | uint8_t	ieee80211_node_get_txrate_dot11rate(struct ieee80211_node *); |
| 546 | void	ieee80211_node_get_txrate(struct ieee80211_node *, |
| 547 | 		struct ieee80211_node_txrate *); |
| 548 | void	ieee80211_node_set_txrate(struct ieee80211_node *, |
| 549 | 	 const struct ieee80211_node_txrate *); |
| 550 | void	ieee80211_node_set_txrate_dot11rate(struct ieee80211_node *, uint8_t); |
| 551 | void	ieee80211_node_set_txrate_ht_mcsrate(struct ieee80211_node *, uint8_t); |
| 552 | uint32_t	ieee80211_node_get_txrate_kbit(struct ieee80211_node *); |
| 553 | void	ieee80211_node_set_txrate_vht_rate(struct ieee80211_node *ni, |
| 554 | 	 uint8_t nss, uint8_t mcs); |
| 555 | |
| 556 | #endif /* _NET80211_IEEE80211_NODE_H_ */ |