Attachment 'net80211-ratectl-ath-final.diff'

Download

   1 Index: sys/dev/ral/rt2560.c
   2 ===================================================================
   3 --- sys/dev/ral/rt2560.c	(revision 254826)
   4 +++ sys/dev/ral/rt2560.c	(working copy)
   5 @@ -426,7 +426,8 @@
   6  	vap->iv_newstate = rt2560_newstate;
   7  	vap->iv_update_beacon = rt2560_beacon_update;
   8  
   9 -	ieee80211_ratectl_init(vap);
  10 +	/* XXX TODO fill the cap */
  11 +	ieee80211_ratectl_init(vap, 0);
  12  	/* complete setup */
  13  	ieee80211_vap_attach(vap, ieee80211_media_change, ieee80211_media_status);
  14  	if (TAILQ_FIRST(&ic->ic_vaps) == vap)
  15 @@ -955,9 +956,13 @@
  16  
  17  			DPRINTFN(sc, 10, "%s\n", "data frame sent successfully");
  18  			if (data->rix != IEEE80211_FIXED_RATE_NONE)
  19 +				ieee80211_ratectl_tx_complete(vap, ni, NULL); /* just make it compiled. qcc */
  20 +#if 0
  21  				ieee80211_ratectl_tx_complete(vap, ni,
  22  				    IEEE80211_RATECTL_TX_SUCCESS,
  23  				    &retrycnt, NULL);
  24 +#endif
  25 +
  26  			ifp->if_opackets++;
  27  			break;
  28  
  29 @@ -967,9 +972,12 @@
  30  			DPRINTFN(sc, 9, "data frame sent after %u retries\n",
  31  			    retrycnt);
  32  			if (data->rix != IEEE80211_FIXED_RATE_NONE)
  33 +				ieee80211_ratectl_tx_complete(vap, ni, NULL); /* just make it compiled. qcc */
  34 +#if 0
  35  				ieee80211_ratectl_tx_complete(vap, ni,
  36  				    IEEE80211_RATECTL_TX_SUCCESS,
  37  				    &retrycnt, NULL);
  38 +#endif
  39  			ifp->if_opackets++;
  40  			break;
  41  
  42 @@ -979,9 +987,12 @@
  43  			DPRINTFN(sc, 9, "data frame failed after %d retries\n",
  44  			    retrycnt);
  45  			if (data->rix != IEEE80211_FIXED_RATE_NONE)
  46 +				ieee80211_ratectl_tx_complete(vap, ni, NULL); /* just make it compiled. qcc */
  47 +#if 0
  48  				ieee80211_ratectl_tx_complete(vap, ni,
  49  				    IEEE80211_RATECTL_TX_FAILURE,
  50  				    &retrycnt, NULL);
  51 +#endif
  52  			ifp->if_oerrors++;
  53  			break;
  54  
  55 Index: sys/dev/ral/rt2661.c
  56 ===================================================================
  57 --- sys/dev/ral/rt2661.c	(revision 254826)
  58 +++ sys/dev/ral/rt2661.c	(working copy)
  59 @@ -423,7 +423,8 @@
  60  	vap->iv_update_beacon = rt2661_beacon_update;
  61  #endif
  62  
  63 -	ieee80211_ratectl_init(vap);
  64 +	/* XXX TODO fill the cap */
  65 +	ieee80211_ratectl_init(vap, 0);
  66  	/* complete setup */
  67  	ieee80211_vap_attach(vap, ieee80211_media_change, ieee80211_media_status);
  68  	if (TAILQ_FIRST(&ic->ic_vaps) == vap)
  69 @@ -905,9 +906,12 @@
  70  			DPRINTFN(sc, 10, "data frame sent successfully after "
  71  			    "%d retries\n", retrycnt);
  72  			if (data->rix != IEEE80211_FIXED_RATE_NONE)
  73 +				ieee80211_ratectl_tx_complete(vap, ni, NULL); /* just make it compiled. qcc */
  74 +#if 0
  75  				ieee80211_ratectl_tx_complete(vap, ni,
  76  				    IEEE80211_RATECTL_TX_SUCCESS,
  77  				    &retrycnt, NULL);
  78 +#endif
  79  			ifp->if_opackets++;
  80  			break;
  81  
  82 @@ -917,9 +921,12 @@
  83  			DPRINTFN(sc, 9, "%s\n",
  84  			    "sending data frame failed (too much retries)");
  85  			if (data->rix != IEEE80211_FIXED_RATE_NONE)
  86 +				ieee80211_ratectl_tx_complete(vap, ni, NULL); /* just make it compiled. qcc */
  87 +#if 0
  88  				ieee80211_ratectl_tx_complete(vap, ni,
  89  				    IEEE80211_RATECTL_TX_FAILURE,
  90  				    &retrycnt, NULL);
  91 +#endif
  92  			ifp->if_oerrors++;
  93  			break;
  94  
  95 Index: sys/dev/ral/rt2860.c
  96 ===================================================================
  97 --- sys/dev/ral/rt2860.c	(revision 254826)
  98 +++ sys/dev/ral/rt2860.c	(working copy)
  99 @@ -484,7 +484,8 @@
 100  	/* HW supports up to 255 STAs (0-254) in HostAP and IBSS modes */
 101  	vap->iv_max_aid = min(IEEE80211_AID_MAX, RT2860_WCID_MAX);
 102  
 103 -	ieee80211_ratectl_init(vap);
 104 +	/* XXX TODO fill the cap */
 105 +	ieee80211_ratectl_init(vap, 0);
 106  	/* complete setup */
 107  	ieee80211_vap_attach(vap, ieee80211_media_change, ieee80211_media_status);
 108  	if (TAILQ_FIRST(&ic->ic_vaps) == vap)
 109 @@ -1121,11 +1122,17 @@
 110  				retrycnt = 1;
 111  			else
 112  				retrycnt = 0;
 113 +			ieee80211_ratectl_tx_complete(ni->ni_vap, ni, NULL); /* just make it compiled. qcc */
 114 +#if 0
 115  			ieee80211_ratectl_tx_complete(ni->ni_vap, ni,
 116  			    IEEE80211_RATECTL_TX_SUCCESS, &retrycnt, NULL);
 117 +#endif
 118  		} else {
 119 +			ieee80211_ratectl_tx_complete(ni->ni_vap, ni, NULL); /* just make it compiled. qcc */
 120 +#if 0
 121  			ieee80211_ratectl_tx_complete(ni->ni_vap, ni,
 122  			    IEEE80211_RATECTL_TX_FAILURE, &retrycnt, NULL);
 123 +#endif
 124  			ifp->if_oerrors++;
 125  		}
 126  	}
 127 Index: sys/dev/ath/if_ath_tx.c
 128 ===================================================================
 129 --- sys/dev/ath/if_ath_tx.c	(revision 254826)
 130 +++ sys/dev/ath/if_ath_tx.c	(working copy)
 131 @@ -72,6 +72,8 @@
 132  
 133  #include <net80211/ieee80211_var.h>
 134  #include <net80211/ieee80211_regdomain.h>
 135 +
 136 +#include <net80211/ieee80211_ratectl.h>
 137  #ifdef IEEE80211_SUPPORT_SUPERG
 138  #include <net80211/ieee80211_superg.h>
 139  #endif
 140 @@ -1387,6 +1389,9 @@
 141  static void
 142  ath_tx_do_ratelookup(struct ath_softc *sc, struct ath_buf *bf)
 143  {
 144 +	struct ieee80211_node *ni = bf->bf_node;
 145 +	struct ieee80211_rc_info *rc_info = NULL;
 146 +	struct ieee80211_rc_series *rc = NULL;
 147  	uint8_t rate, rix;
 148  	int try0;
 149  
 150 @@ -1395,7 +1400,7 @@
 151  
 152  	/* Get rid of any previous state */
 153  	bzero(bf->bf_state.bfs_rc, sizeof(bf->bf_state.bfs_rc));
 154 -
 155 +#if 0
 156  	ATH_NODE_LOCK(ATH_NODE(bf->bf_node));
 157  	ath_rate_findrate(sc, ATH_NODE(bf->bf_node), bf->bf_state.bfs_shpream,
 158  	    bf->bf_state.bfs_pktlen, &rix, &try0, &rate);
 159 @@ -1409,7 +1414,25 @@
 160  		ath_rate_getxtxrates(sc, ATH_NODE(bf->bf_node), rix,
 161  		    bf->bf_state.bfs_rc);
 162  	ATH_NODE_UNLOCK(ATH_NODE(bf->bf_node));
 163 +#endif
 164  
 165 +	/* net80211 ratectl */
 166 +	rc_info = ieee80211_ratectl_rc_info_get(ni, bf->bf_m);
 167 +	rc = rc_info->iri_rc;
 168 +	
 169 +	rc_info->iri_flags = 0;
 170 +	if (bf->bf_state.bfs_shpream)
 171 +		rc_info->iri_flags |= IEEE80211_RATECTL_INFO_SP;
 172 +	if (bf->bf_state.bfs_aggr)
 173 +		rc_info->iri_flags |= IEEE80211_RATECTL_INFO_AGGR;
 174 +	rc_info->iri_framelen = bf->bf_state.bfs_pktlen;
 175 +
 176 +	ieee80211_ratectl_rates(ni, rc_info);
 177 +
 178 +	rix = rc[0].rix;
 179 +	try0 = rc[0].tries;
 180 +	rate = ni->ni_txrate;
 181 +
 182  	sc->sc_txrix = rix;	/* for LED blinking */
 183  	sc->sc_lastdatarix = rix;	/* for fast frames */
 184  	bf->bf_state.bfs_try0 = try0;
 185 @@ -1530,7 +1553,8 @@
 186  	 * frames that must go out - eg management/raw frames.
 187  	 */
 188  	bf->bf_state.bfs_txflags |= HAL_TXDESC_CLRDMASK;
 189 -
 190 +	
 191 +	bf->bf_state.bfs_aggr = 0;
 192  	/* Setup the descriptor before handoff */
 193  	ath_tx_do_ratelookup(sc, bf);
 194  	ath_tx_calc_duration(sc, bf);
 195 @@ -4058,6 +4082,7 @@
 196  	int tid = bf->bf_state.bfs_tid;
 197  	struct ath_tid *atid = &an->an_tid[tid];
 198  	struct ath_tx_status *ts = &bf->bf_status.ds_txstat;
 199 +	struct ieee80211_rc_info *rc_info = NULL;
 200  
 201  	/* The TID state is protected behind the TXQ lock */
 202  	ATH_TX_LOCK(sc);
 203 @@ -4108,9 +4133,23 @@
 204  	 * during a hw queue drain and the frame wanted an ACK.
 205  	 */
 206  	if (fail == 0 && ((bf->bf_state.bfs_txflags & HAL_TXDESC_NOACK) == 0))
 207 +	{
 208 +#if 0
 209  		ath_tx_update_ratectrl(sc, ni, bf->bf_state.bfs_rc,
 210  		    ts, bf->bf_state.bfs_pktlen,
 211  		    1, (ts->ts_status == 0) ? 0 : 1);
 212 +#endif
 213 +	
 214 +		/* net80211 ratectl */
 215 +		rc_info = ieee80211_ratectl_rc_info_get(ni, bf->bf_m);
 216 +		ieee80211_ratectl_rc_info_set(rc_info,
 217 +				1, (ts->ts_status == 0 ? 0 : 1), 
 218 +				bf->bf_state.bfs_pktlen,
 219 +				ts->ts_shortretry, ts->ts_longretry,
 220 +				ts->ts_finaltsi, ts->ts_rate);
 221 +		rc_info->iri_flags &= ~IEEE80211_RATECTL_INFO_AGGR;	
 222 +		ieee80211_ratectl_tx_complete(ni->ni_vap, ni, rc_info);
 223 +	}
 224  
 225  	ath_tx_default_comp(sc, bf, fail);
 226  }
 227 @@ -4475,6 +4514,8 @@
 228  	int drops = 0;
 229  	struct ieee80211_tx_ampdu *tap;
 230  	ath_bufhead bf_cq;
 231 +	struct ath_tx_status ts = bf_first->bf_status.ds_txstat;
 232 +	struct ieee80211_rc_info *rc_info = NULL;
 233  
 234  	TAILQ_INIT(&bf_q);
 235  	TAILQ_INIT(&bf_cq);
 236 @@ -4485,10 +4526,23 @@
 237  	 * XXX use the length in the first frame in the series;
 238  	 * XXX just so things are consistent for now.
 239  	 */
 240 +#if 0
 241  	ath_tx_update_ratectrl(sc, ni, bf_first->bf_state.bfs_rc,
 242  	    &bf_first->bf_status.ds_txstat,
 243  	    bf_first->bf_state.bfs_pktlen,
 244  	    bf_first->bf_state.bfs_nframes, bf_first->bf_state.bfs_nframes);
 245 +#endif
 246 +	
 247 +	/* net80211 ratectl */
 248 +	rc_info = ieee80211_ratectl_rc_info_get(ni, bf_first->bf_m);
 249 +	ieee80211_ratectl_rc_info_set(rc_info,
 250 +			bf_first->bf_state.bfs_nframes, 
 251 +			bf_first->bf_state.bfs_nframes,
 252 +			bf_first->bf_state.bfs_pktlen,
 253 +			ts.ts_shortretry, ts.ts_longretry,
 254 +			ts.ts_finaltsi, ts.ts_rate);
 255 +	rc_info->iri_flags |= IEEE80211_RATECTL_INFO_AGGR;
 256 +	ieee80211_ratectl_tx_complete(ni->ni_vap, ni, rc_info);
 257  
 258  	ATH_TX_LOCK(sc);
 259  	tap = ath_tx_get_tx_tid(an, tid->tid);
 260 @@ -4626,9 +4680,12 @@
 261  	int nframes = 0, nbad = 0, nf;
 262  	int pktlen;
 263  	/* XXX there's too much on the stack? */
 264 +#if 0
 265  	struct ath_rc_series rc[ATH_RC_NUM];
 266 +#endif
 267  	int txseq;
 268 -
 269 +	struct ieee80211_rc_info *rc_info = NULL;
 270 +	struct mbuf *m;
 271  	DPRINTF(sc, ATH_DEBUG_SW_TX_AGGR, "%s: called; hwq_depth=%d\n",
 272  	    __func__, atid->hwq_depth);
 273  
 274 @@ -4748,7 +4805,7 @@
 275  	isaggr = bf_first->bf_state.bfs_aggr;
 276  	ba[0] = ts.ts_ba_low;
 277  	ba[1] = ts.ts_ba_high;
 278 -
 279 +#if 0
 280  	/*
 281  	 * Copy the TX completion status and the rate control
 282  	 * series from the first descriptor, as it may be freed
 283 @@ -4756,6 +4813,11 @@
 284  	 * into things.
 285  	 */
 286  	memcpy(rc, bf_first->bf_state.bfs_rc, sizeof(rc));
 287 +#endif
 288 +	/* 
 289 +	 * Get the mbuf here, as bf_first will be set to NULL later. 
 290 +	 */
 291 +	m = bf_first->bf_m; 
 292  
 293  	DPRINTF(sc, ATH_DEBUG_SW_TX_AGGR,
 294  	    "%s: txa_start=%d, tx_ok=%d, status=%.8x, flags=%.8x, "
 295 @@ -4873,8 +4935,20 @@
 296  	 * control code.
 297  	 */
 298  	if (fail == 0)
 299 +	{
 300 +#if 0	
 301  		ath_tx_update_ratectrl(sc, ni, rc, &ts, pktlen, nframes,
 302  		    nbad);
 303 +#endif
 304 +		/* net80211 ratectl */
 305 +		rc_info = ieee80211_ratectl_rc_info_get(ni, m);
 306 +		ieee80211_ratectl_rc_info_set(rc_info,
 307 +					nframes, nbad, pktlen,
 308 +					ts.ts_shortretry, ts.ts_longretry,
 309 +					ts.ts_finaltsi, ts.ts_rate);
 310 +		rc_info->iri_flags |= IEEE80211_RATECTL_INFO_AGGR;
 311 +		ieee80211_ratectl_tx_complete(ni->ni_vap, ni, rc_info);
 312 +	}
 313  
 314  	/*
 315  	 * send bar if we dropped any frames
 316 @@ -4948,6 +5022,7 @@
 317  	struct ath_tid *atid = &an->an_tid[tid];
 318  	struct ath_tx_status ts;
 319  	int drops = 0;
 320 +	struct ieee80211_rc_info *rc_info = NULL;
 321  
 322  	/*
 323  	 * Take a copy of this; filtering/cloning the frame may free the
 324 @@ -4962,11 +5037,22 @@
 325  	 * Do it outside of the TXQ lock.
 326  	 */
 327  	if (fail == 0 && ((bf->bf_state.bfs_txflags & HAL_TXDESC_NOACK) == 0))
 328 +	{
 329 +#if 0	
 330  		ath_tx_update_ratectrl(sc, ni, bf->bf_state.bfs_rc,
 331  		    &bf->bf_status.ds_txstat,
 332  		    bf->bf_state.bfs_pktlen,
 333  		    1, (ts.ts_status == 0) ? 0 : 1);
 334 -
 335 +#endif
 336 +		rc_info = ieee80211_ratectl_rc_info_get(ni, bf->bf_m);
 337 +		ieee80211_ratectl_rc_info_set(rc_info,
 338 +				1, (ts.ts_status == 0 ? 0 : 1), 
 339 +				bf->bf_state.bfs_pktlen,
 340 +				ts.ts_shortretry, ts.ts_longretry,
 341 +				ts.ts_finaltsi, ts.ts_rate);
 342 +		rc_info->iri_flags &= ~IEEE80211_RATECTL_INFO_AGGR;
 343 +		ieee80211_ratectl_tx_complete(ni->ni_vap, ni, rc_info);
 344 +	}
 345  	/*
 346  	 * This is called early so atid->hwq_depth can be tracked.
 347  	 * This unfortunately means that it's released and regrabbed
 348 @@ -5183,6 +5269,15 @@
 349  		}
 350  
 351  		/*
 352 +		 * If non-aggregate scenario appears, this will be 
 353 +		 * turned off.
 354 +		 *
 355 +		 * This flag is used by ath_tx_do_ratelookup() to 
 356 +		 * distinguish aggr/non-aggr scenario.  
 357 +		 */
 358 +		bf->bf_state.bfs_aggr = 1;
 359 +
 360 +		/*
 361  		 * If the packet doesn't fall within the BAW (eg a NULL
 362  		 * data frame), schedule it directly; continue.
 363  		 */
 364 @@ -5425,6 +5520,7 @@
 365  		/* Update CLRDMASK just before this frame is queued */
 366  		ath_tx_update_clrdmask(sc, tid, bf);
 367  
 368 +		bf->bf_state.bfs_aggr = 0; 
 369  		/* Program descriptors + rate control */
 370  		ath_tx_do_ratelookup(sc, bf);
 371  		ath_tx_calc_duration(sc, bf);
 372 Index: sys/dev/ath/if_ath_tx_ht.c
 373 ===================================================================
 374 --- sys/dev/ath/if_ath_tx_ht.c	(revision 254826)
 375 +++ sys/dev/ath/if_ath_tx_ht.c	(working copy)
 376 @@ -64,6 +64,8 @@
 377  
 378  #include <net80211/ieee80211_var.h>
 379  #include <net80211/ieee80211_regdomain.h>
 380 +
 381 +#include <net80211/ieee80211_ratectl.h>
 382  #ifdef IEEE80211_SUPPORT_SUPERG
 383  #include <net80211/ieee80211_superg.h>
 384  #endif
 385 @@ -221,13 +223,47 @@
 386  void
 387  ath_tx_rate_fill_rcflags(struct ath_softc *sc, struct ath_buf *bf)
 388  {
 389 -	struct ieee80211_node *ni = bf->bf_node;
 390 -	struct ieee80211com *ic = ni->ni_ic;
 391 +	// struct ieee80211_node *ni = bf->bf_node;
 392 +	// struct ieee80211com *ic = ni->ni_ic;
 393  	const HAL_RATE_TABLE *rt = sc->sc_currates;
 394 -	struct ath_rc_series *rc = bf->bf_state.bfs_rc;
 395 +	struct ath_rc_series *ath_rc = bf->bf_state.bfs_rc;
 396 +	struct ieee80211_rc_info *rc_info = NULL;
 397 +	struct ieee80211_rc_series *rc = NULL;
 398 +	struct m_tag *mtag;
 399  	uint8_t rate;
 400  	int i;
 401  
 402 +	mtag = m_tag_locate(bf->bf_m, MTAG_ABI_NET80211, 
 403 +			NET80211_TAG_RATECTL, NULL);
 404 +	if (NULL == mtag)
 405 +		return;
 406 +
 407 +	rc_info = (struct ieee80211_rc_info*)(mtag + 1);
 408 +	rc = rc_info->iri_rc;
 409 +
 410 +	for (i = 0; i < IEEE80211_RATECTL_NUM; i++) {
 411 +		if (rc[i].tries == 0)
 412 +			continue;
 413 +
 414 +		rate = rt->info[rc[i].rix].rateCode;
 415 +		if (rc[i].flags & IEEE80211_RATECTL_FLAG_SP)
 416 +			rate |= rt->info[rc[i].rix].shortPreamble;
 417 +
 418 +		rc[i].ratecode = rate;
 419 +
 420 +		ath_rc[i].rix = rc[i].rix;
 421 +		ath_rc[i].tries = rc[i].tries;
 422 +		ath_rc[i].flags = rc[i].flags;
 423 +		ath_rc[i].ratecode = rc[i].ratecode;
 424 +		ath_rc[i].tx_power_cap = rc[i].tx_power_cap;
 425 +		ath_rc[i].max4msframelen = rc[i].max4msframelen;
 426 +		
 427 +		DPRINTF(sc, ATH_DEBUG_SW_TX_AGGR,
 428 +		    "%s: i=%d, rate=0x%x, flags=0x%x, max4ms=%d\n",
 429 +		    __func__, i, rate, rc[i].flags, rc[i].max4msframelen);
 430 +	}
 431 +
 432 +#if 0
 433  	for (i = 0; i < ATH_RC_NUM; i++) {
 434  		rc[i].flags = 0;
 435  		if (rc[i].tries == 0)
 436 @@ -325,6 +361,7 @@
 437  		    "%s: i=%d, rate=0x%x, flags=0x%x, max4ms=%d\n",
 438  		    __func__, i, rate, rc[i].flags, rc[i].max4msframelen);
 439  	}
 440 +#endif
 441  }
 442  
 443  /*
 444 Index: sys/dev/ath/if_ath.c
 445 ===================================================================
 446 --- sys/dev/ath/if_ath.c	(revision 254826)
 447 +++ sys/dev/ath/if_ath.c	(working copy)
 448 @@ -82,6 +82,8 @@
 449  
 450  #include <net80211/ieee80211_var.h>
 451  #include <net80211/ieee80211_regdomain.h>
 452 +
 453 +#include <net80211/ieee80211_ratectl.h>
 454  #ifdef IEEE80211_SUPPORT_SUPERG
 455  #include <net80211/ieee80211_superg.h>
 456  #endif
 457 @@ -322,6 +324,7 @@
 458  	sc->sc_ah = ah;
 459  	sc->sc_invalid = 0;	/* ready to go, enable interrupt handling */
 460  #ifdef	ATH_DEBUG
 461 +	ath_debug |= ATH_DEBUG_NODE; 
 462  	sc->sc_debug = ath_debug;
 463  #endif
 464  
 465 @@ -1380,6 +1383,16 @@
 466  	}
 467  	ATH_UNLOCK(sc);
 468  
 469 +	uint32_t caps = 0;
 470 +	if (sc->sc_mrretry)
 471 +		caps |= IEEE80211_RATECTL_CAP_MRR;
 472 +	if (sc->sc_mrrprot)
 473 +		caps |= IEEE80211_RATECTL_CAP_MRRPROT;
 474 +	if (sc->sc_txchainmask > 1)
 475 +		caps |= IEEE80211_RATECTL_CAP_MULTXCHAIN;
 476 +
 477 +	ieee80211_ratectl_init(vap, caps);
 478 +	
 479  	/* complete setup */
 480  	ieee80211_vap_attach(vap, ath_media_change, ieee80211_media_status);
 481  	return vap;
 482 @@ -1414,6 +1427,7 @@
 483  		ath_stoprecv(sc, 1);		/* stop recv side */
 484  	}
 485  
 486 +	ieee80211_ratectl_deinit(vap);
 487  	ieee80211_vap_detach(vap);
 488  
 489  	/*
 490 @@ -4042,6 +4056,7 @@
 491  {
 492  	struct ieee80211_node *ni = bf->bf_node;
 493  	struct ath_node *an = NULL;
 494 +	struct ieee80211_rc_info *rc_info = NULL;
 495  
 496  	ATH_TX_UNLOCK_ASSERT(sc);
 497  	ATH_TXQ_UNLOCK_ASSERT(txq);
 498 @@ -4068,10 +4083,21 @@
 499  			 * XXX assume this isn't an aggregate
 500  			 * frame.
 501  			 */
 502 +#if 0
 503  			ath_tx_update_ratectrl(sc, ni,
 504  			     bf->bf_state.bfs_rc, ts,
 505  			    bf->bf_state.bfs_pktlen, 1,
 506  			    (ts->ts_status == 0 ? 0 : 1));
 507 +#endif
 508 +			/* net80211 ratectl */
 509 +			rc_info = ieee80211_ratectl_rc_info_get(ni, bf->bf_m);
 510 +			ieee80211_ratectl_rc_info_set(rc_info,
 511 +					1, (ts->ts_status == 0 ? 0 : 1), 
 512 +					bf->bf_state.bfs_pktlen,
 513 +					ts->ts_shortretry, ts->ts_longretry,
 514 +					ts->ts_finaltsi, ts->ts_rate);
 515 +			rc_info->iri_flags &= ~IEEE80211_RATECTL_INFO_AGGR;	
 516 +			ieee80211_ratectl_tx_complete(ni->ni_vap, ni, rc_info);
 517  		}
 518  		ath_tx_default_comp(sc, bf, 0);
 519  	} else
 520 @@ -5574,9 +5600,15 @@
 521  
 522  	an->an_mcastrix = ath_tx_findrix(sc, tp->mcastrate);
 523  	an->an_mgmtrix = ath_tx_findrix(sc, tp->mgmtrate);
 524 -
 525 +#if 0
 526  	ath_rate_newassoc(sc, an, isnew);
 527 +#endif
 528  
 529 +	DPRINTF(sc, ATH_DEBUG_NODE, "%s: newassoc is new: %d\n",
 530 +			__func__, isnew);
 531 +	if (isnew)
 532 +		ieee80211_ratectl_node_init(ni);
 533 +
 534  	if (isnew &&
 535  	    (vap->iv_flags & IEEE80211_F_PRIVACY) == 0 && sc->sc_hasclrkey &&
 536  	    ni->ni_ucastkey.wk_keyix == IEEE80211_KEYIX_NONE)
 537 Index: sys/dev/ath/if_ath_sysctl.c
 538 ===================================================================
 539 --- sys/dev/ath/if_ath_sysctl.c	(revision 254826)
 540 +++ sys/dev/ath/if_ath_sysctl.c	(working copy)
 541 @@ -71,6 +71,7 @@
 542  
 543  #include <net80211/ieee80211_var.h>
 544  #include <net80211/ieee80211_regdomain.h>
 545 +#include <net80211/ieee80211_ratectl.h>
 546  #ifdef IEEE80211_SUPPORT_SUPERG
 547  #include <net80211/ieee80211_superg.h>
 548  #endif
 549 @@ -602,6 +603,28 @@
 550  }
 551  #endif /* ATH_DEBUG_ALQ */
 552  
 553 +static int
 554 +ath_sysctl_ratectl_stats(SYSCTL_HANDLER_ARGS)
 555 +{
 556 +	struct ath_softc *sc = arg1;
 557 +	struct ieee80211com *ic = sc->sc_ifp->if_l2com; 
 558 +	struct ieee80211vap *vap;
 559 +	int error, v;
 560 +
 561 +	v = 0;
 562 +	error = sysctl_handle_int(oidp, &v, 0, req);
 563 +	if (error || !req->newptr)
 564 +		return error;
 565 +
 566 +	printf("\n[%s]: per-device net80211 ratectl statistics\n", 
 567 +			ic->ic_ifp->if_xname);
 568 +	TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
 569 +		ieee80211_ratectl_stats(vap);
 570 +	}
 571 +		
 572 +	return 0;
 573 +}
 574 +
 575  void
 576  ath_sysctlattach(struct ath_softc *sc)
 577  {
 578 @@ -792,6 +815,10 @@
 579  #ifdef	ATH_DEBUG_ALQ
 580  	ath_sysctl_alq_attach(sc);
 581  #endif
 582 +	
 583 +	SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
 584 +		"ratectl_stats", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
 585 +		ath_sysctl_ratectl_stats, "I", "per-device net80211 ratectl statistics");
 586  }
 587  
 588  static int
 589 Index: sys/dev/iwn/if_iwn.c
 590 ===================================================================
 591 --- sys/dev/iwn/if_iwn.c	(revision 254826)
 592 +++ sys/dev/iwn/if_iwn.c	(working copy)
 593 @@ -876,7 +876,8 @@
 594  	ivp->iv_newstate = vap->iv_newstate;
 595  	vap->iv_newstate = iwn_newstate;
 596  
 597 -	ieee80211_ratectl_init(vap);
 598 +	/* XXX TODO fill the cap */
 599 +	ieee80211_ratectl_init(vap, 0);
 600  	/* Complete setup. */
 601  	ieee80211_vap_attach(vap, iwn_media_change, ieee80211_media_status);
 602  	ic->ic_opmode = opmode;
 603 @@ -2499,7 +2500,8 @@
 604  	uint64_t bitmap;
 605  	uint16_t ssn;
 606  	uint8_t tid;
 607 -	int ackfailcnt = 0, i, lastidx, qid, *res, shift;
 608 +	/* int failcnt = 0; */
 609 +	int i, lastidx, qid, *res, shift;
 610  
 611  	bus_dmamap_sync(sc->rxq.data_dmat, data->map, BUS_DMASYNC_POSTREAD);
 612  
 613 @@ -2563,12 +2565,18 @@
 614  	for (i = 0; bitmap; i++) {
 615  		if ((bitmap & 1) == 0) {
 616  			ifp->if_oerrors++;
 617 +#if 0
 618  			ieee80211_ratectl_tx_complete(ni->ni_vap, ni,
 619  			    IEEE80211_RATECTL_TX_FAILURE, &ackfailcnt, NULL);
 620 +#endif
 621 +		ieee80211_ratectl_tx_complete(ni->ni_vap, ni, NULL); /* just make it compiled. qcc */	
 622  		} else {
 623  			ifp->if_opackets++;
 624 +#if 0
 625  			ieee80211_ratectl_tx_complete(ni->ni_vap, ni,
 626  			    IEEE80211_RATECTL_TX_SUCCESS, &ackfailcnt, NULL);
 627 +#endif
 628 +			ieee80211_ratectl_tx_complete(ni->ni_vap, ni, NULL); /* just make it compiled. qcc */
 629  		}
 630  		bitmap >>= 1;
 631  	}
 632 @@ -2807,12 +2815,18 @@
 633  	 */
 634  	if (status & IWN_TX_FAIL) {
 635  		ifp->if_oerrors++;
 636 +#if 0
 637  		ieee80211_ratectl_tx_complete(vap, ni,
 638  		    IEEE80211_RATECTL_TX_FAILURE, &ackfailcnt, NULL);
 639 +#endif
 640 +		ieee80211_ratectl_tx_complete(vap, ni, NULL); /* just make it compiled. qcc */
 641  	} else {
 642  		ifp->if_opackets++;
 643 +#if 0
 644  		ieee80211_ratectl_tx_complete(vap, ni,
 645  		    IEEE80211_RATECTL_TX_SUCCESS, &ackfailcnt, NULL);
 646 +#endif
 647 +		ieee80211_ratectl_tx_complete(vap, ni, NULL); /* just make it compiled. qcc */
 648  	}
 649  	m_freem(m);
 650  	ieee80211_free_node(ni);
 651 Index: sys/dev/bwi/if_bwi.c
 652 ===================================================================
 653 --- sys/dev/bwi/if_bwi.c	(revision 254826)
 654 +++ sys/dev/bwi/if_bwi.c	(working copy)
 655 @@ -617,7 +617,8 @@
 656  #if 0
 657  	vap->iv_update_beacon = bwi_beacon_update;
 658  #endif
 659 -	ieee80211_ratectl_init(vap);
 660 +	/* XXX TODO fill the cap */
 661 +	ieee80211_ratectl_init(vap, 0);
 662  
 663  	/* complete setup */
 664  	ieee80211_vap_attach(vap, bwi_media_change, ieee80211_media_status);
 665 @@ -3377,9 +3378,12 @@
 666  			 * well so to avoid over-aggressive downshifting we
 667  			 * treat any number of retries as "1".
 668  			 */
 669 +#if 0
 670  			ieee80211_ratectl_tx_complete(vap, ni,
 671  			    (data_txcnt > 1) ? IEEE80211_RATECTL_TX_SUCCESS :
 672  			        IEEE80211_RATECTL_TX_FAILURE, &acked, NULL);
 673 +#endif
 674 +			ieee80211_ratectl_tx_complete(vap, ni, NULL); /* just make it compiled. qcc */
 675  		}
 676  
 677  		/*
 678 Index: sys/dev/bwn/if_bwn.c
 679 ===================================================================
 680 --- sys/dev/bwn/if_bwn.c	(revision 254826)
 681 +++ sys/dev/bwn/if_bwn.c	(working copy)
 682 @@ -2970,7 +2970,8 @@
 683  	/* override max aid so sta's cannot assoc when we're out of sta id's */
 684  	vap->iv_max_aid = BWN_STAID_MAX;
 685  
 686 -	ieee80211_ratectl_init(vap);
 687 +	/* XXX TODO fill the cap */
 688 +	ieee80211_ratectl_init(vap, 0);
 689  
 690  	/* complete setup */
 691  	ieee80211_vap_attach(vap, ieee80211_media_change,
 692 @@ -8991,8 +8992,9 @@
 693  	struct bwn_stats *stats = &mac->mac_stats;
 694  	struct ieee80211_node *ni;
 695  	struct ieee80211vap *vap;
 696 -	int retrycnt = 0, slot;
 697 -
 698 +	/*int retrycnt = 0, slot;*/
 699 +	int slot;
 700 +	
 701  	BWN_ASSERT_LOCKED(mac->mac_sc);
 702  
 703  	if (status->im)
 704 @@ -9020,11 +9022,14 @@
 705  				if (meta->mt_islast) {
 706  					ni = meta->mt_ni;
 707  					vap = ni->ni_vap;
 708 +#if 0
 709  					ieee80211_ratectl_tx_complete(vap, ni,
 710  					    status->ack ?
 711  					      IEEE80211_RATECTL_TX_SUCCESS :
 712  					      IEEE80211_RATECTL_TX_FAILURE,
 713  					    &retrycnt, 0);
 714 +#endif
 715 +					ieee80211_ratectl_tx_complete(vap, ni, NULL); /* just make it compiled. qcc */
 716  					break;
 717  				}
 718  				slot = bwn_dma_nextslot(dr, slot);
 719 @@ -9041,11 +9046,14 @@
 720  			}
 721  			ni = tp->tp_ni;
 722  			vap = ni->ni_vap;
 723 +#if 0
 724  			ieee80211_ratectl_tx_complete(vap, ni,
 725  			    status->ack ?
 726  			      IEEE80211_RATECTL_TX_SUCCESS :
 727  			      IEEE80211_RATECTL_TX_FAILURE,
 728  			    &retrycnt, 0);
 729 +#endif
 730 +			ieee80211_ratectl_tx_complete(vap, ni, NULL); /* just make it compiled. qcc */
 731  		}
 732  		bwn_pio_handle_txeof(mac, status);
 733  	}
 734 Index: sys/dev/usb/wlan/if_zyd.c
 735 ===================================================================
 736 --- sys/dev/usb/wlan/if_zyd.c	(revision 254826)
 737 +++ sys/dev/usb/wlan/if_zyd.c	(working copy)
 738 @@ -496,7 +496,8 @@
 739  	zvp->newstate = vap->iv_newstate;
 740  	vap->iv_newstate = zyd_newstate;
 741  
 742 -	ieee80211_ratectl_init(vap);
 743 +	/* XXX TODO fill the cap */
 744 +	ieee80211_ratectl_init(vap, 0);
 745  	ieee80211_ratectl_setinterval(vap, 1000 /* 1 sec */);
 746  
 747  	/* complete setup */
 748 @@ -664,12 +665,15 @@
 749  			 */
 750  			ni = ieee80211_find_txnode(vap, retry->macaddr);
 751  			if (ni != NULL) {
 752 -				int retrycnt =
 753 -				    (int)(le16toh(retry->count) & 0xff);
 754 +				/*int retrycnt =
 755 +				    (int)(le16toh(retry->count) & 0xff);*/
 756  				
 757 +#if 0
 758  				ieee80211_ratectl_tx_complete(vap, ni,
 759  				    IEEE80211_RATECTL_TX_FAILURE,
 760  				    &retrycnt, NULL);
 761 +#endif
 762 +				ieee80211_ratectl_tx_complete(vap, ni, NULL); /* just make it compiled. qcc */
 763  				ieee80211_free_node(ni);
 764  			}
 765  			if (le16toh(retry->count) & 0x100)
 766 Index: sys/dev/usb/wlan/if_ural.c
 767 ===================================================================
 768 --- sys/dev/usb/wlan/if_ural.c	(revision 254826)
 769 +++ sys/dev/usb/wlan/if_ural.c	(working copy)
 770 @@ -598,7 +598,8 @@
 771  
 772  	usb_callout_init_mtx(&uvp->ratectl_ch, &sc->sc_mtx, 0);
 773  	TASK_INIT(&uvp->ratectl_task, 0, ural_ratectl_task, uvp);
 774 -	ieee80211_ratectl_init(vap);
 775 +	/* XXX TODO fill the cap */
 776 +	ieee80211_ratectl_init(vap, 0);
 777  	ieee80211_ratectl_setinterval(vap, 1000 /* 1 sec */);
 778  
 779  	/* complete setup */
 780 Index: sys/dev/usb/wlan/if_rum.c
 781 ===================================================================
 782 --- sys/dev/usb/wlan/if_rum.c	(revision 254826)
 783 +++ sys/dev/usb/wlan/if_rum.c	(working copy)
 784 @@ -613,7 +613,8 @@
 785  
 786  	usb_callout_init_mtx(&rvp->ratectl_ch, &sc->sc_mtx, 0);
 787  	TASK_INIT(&rvp->ratectl_task, 0, rum_ratectl_task, rvp);
 788 -	ieee80211_ratectl_init(vap);
 789 +	/* XXX TODO fill the cap */
 790 +	ieee80211_ratectl_init(vap, 0);
 791  	ieee80211_ratectl_setinterval(vap, 1000 /* 1 sec */);
 792  	/* complete setup */
 793  	ieee80211_vap_attach(vap, ieee80211_media_change, ieee80211_media_status);
 794 Index: sys/dev/usb/wlan/if_run.c
 795 ===================================================================
 796 --- sys/dev/usb/wlan/if_run.c	(revision 254826)
 797 +++ sys/dev/usb/wlan/if_run.c	(working copy)
 798 @@ -820,7 +820,8 @@
 799  	rvp->newstate = vap->iv_newstate;
 800  	vap->iv_newstate = run_newstate;
 801  
 802 -	ieee80211_ratectl_init(vap);
 803 +	/* XXX TODO fill the cap */
 804 +	ieee80211_ratectl_init(vap, 0);
 805  	ieee80211_ratectl_setinterval(vap, 1000 /* 1 sec */);
 806  
 807  	/* complete setup */
 808 Index: sys/dev/wpi/if_wpi.c
 809 ===================================================================
 810 --- sys/dev/wpi/if_wpi.c	(revision 254826)
 811 +++ sys/dev/wpi/if_wpi.c	(working copy)
 812 @@ -782,7 +782,8 @@
 813  	wvp->newstate = vap->iv_newstate;
 814  	vap->iv_newstate = wpi_newstate;
 815  
 816 -	ieee80211_ratectl_init(vap);
 817 +	/* XXX TODO fill the cap */
 818 +	ieee80211_ratectl_init(vap, 0);
 819  	/* complete setup */
 820  	ieee80211_vap_attach(vap, ieee80211_media_change, ieee80211_media_status);
 821  	ic->ic_opmode = opmode;
 822 @@ -1596,8 +1597,11 @@
 823  		DPRINTFN(WPI_DEBUG_TX, ("%d retries\n", stat->ntries));
 824  		retrycnt = 1;
 825  	}
 826 +#if 0
 827  	ieee80211_ratectl_tx_complete(vap, ni, IEEE80211_RATECTL_TX_SUCCESS,
 828  	    &retrycnt, NULL);
 829 +#endif
 830 +	ieee80211_ratectl_tx_complete(vap, ni, NULL); /* just make it compiled. qcc */
 831  
 832  	/* XXX oerrors should only count errors !maxtries */
 833  	if ((le32toh(stat->status) & 0xff) != 1)
 834 Index: sys/conf/files
 835 ===================================================================
 836 --- sys/conf/files	(revision 254826)
 837 +++ sys/conf/files	(working copy)
 838 @@ -3100,6 +3100,7 @@
 839  net80211/ieee80211_ratectl_none.c optional wlan
 840  net80211/ieee80211_regdomain.c	optional wlan
 841  net80211/ieee80211_rssadapt.c	optional wlan wlan_rssadapt
 842 +net80211/ieee80211_sample.c	optional wlan | wlan_sample
 843  net80211/ieee80211_scan.c	optional wlan
 844  net80211/ieee80211_scan_sta.c	optional wlan
 845  net80211/ieee80211_sta.c	optional wlan
 846 Index: sys/net80211/ieee80211_ratectl_none.c
 847 ===================================================================
 848 --- sys/net80211/ieee80211_ratectl_none.c	(revision 254826)
 849 +++ sys/net80211/ieee80211_ratectl_none.c	(working copy)
 850 @@ -44,10 +44,26 @@
 851  
 852  #include <net80211/ieee80211_var.h>
 853  #include <net80211/ieee80211_ratectl.h>
 854 +#include <net80211/ieee80211_ratectl_none.h>
 855  
 856  static void
 857 -none_init(struct ieee80211vap *vap)
 858 +none_init(struct ieee80211vap *vap, uint32_t capabilities)
 859  {
 860 +	struct ieee80211_node *none;
 861 +
 862 +	KASSERT(vap->iv_rs == NULL, ("%s called multiple times", __func__));
 863 +
 864 +	none = vap->iv_rs = malloc(sizeof(struct ieee80211_none),
 865 +	    M_80211_RATECTL, M_NOWAIT|M_ZERO);
 866 +	if (none == NULL) {
 867 +		if_printf(vap->iv_ifp, "couldn't alloc ratectl structure\n");
 868 +		return;
 869 +	}
 870 +
 871 +	struct ieee80211_rc_stat * irs = IEEE80211_RATECTL_STAT(vap);
 872 +	irs->irs_capabilities = capabilities;
 873 +
 874 +	/* ... */
 875  }
 876  
 877  static void
 878 @@ -59,6 +75,25 @@
 879  static void
 880  none_node_init(struct ieee80211_node *ni)
 881  {
 882 +	struct ieee80211vap *vap = ni->ni_vap;
 883 +	struct ieee80211_none *none = vap->iv_rs;
 884 +	struct ieee80211_none_node *non;
 885 +
 886 +	if (ni->ni_rctls == NULL) {
 887 +		ni->ni_rctls = non = malloc(sizeof(struct ieee80211_none_node),
 888 +		    M_80211_RATECTL, M_NOWAIT|M_ZERO);
 889 +		if (non == NULL) {
 890 +			if_printf(vap->iv_ifp, "couldn't alloc per-node ratectl "
 891 +			    "structure\n");
 892 +			return;
 893 +		}
 894 +	} else
 895 +		non = ni->ni_rctls;
 896 +
 897 +	non->non_none = none;
 898 +
 899 +	/* ... */
 900 +	
 901  	ni->ni_txrate = ni->ni_rates.rs_rates[0] & IEEE80211_RATE_VAL;
 902  }
 903  
 904 @@ -77,9 +112,13 @@
 905  }
 906  
 907  static void
 908 +none_rates(struct ieee80211_node *ni, struct ieee80211_rc_info *rc_info)
 909 +{
 910 +}
 911 +
 912 +static void
 913  none_tx_complete(const struct ieee80211vap *vap,
 914 -    const struct ieee80211_node *ni, int ok,
 915 -    void *arg1, void *arg2 __unused)
 916 +    const struct ieee80211_node *ni, struct ieee80211_rc_info *rc_info)
 917  {
 918  }
 919  
 920 @@ -94,6 +133,16 @@
 921  {
 922  }
 923  
 924 +static void
 925 +none_stats(const struct ieee80211vap *vap)
 926 +{
 927 +	struct ieee80211_rc_stat * irs = IEEE80211_RATECTL_STAT(vap);
 928 +	printf("tx count: %d (ok count: %d, fail count: %d)\n"
 929 +			"retry count: %d (short retry: %d, long retry: %d)\n",
 930 +			irs->irs_txcnt, irs->irs_txcnt - irs->irs_failcnt, irs->irs_failcnt,
 931 +			irs->irs_retrycnt, irs->irs_shortretry, irs->irs_longretry);
 932 +	/* ... */
 933 +}
 934  /* number of references from net80211 layer */
 935  static	int nrefs = 0;
 936  
 937 @@ -106,9 +155,11 @@
 938  	.ir_node_init	= none_node_init,
 939  	.ir_node_deinit	= none_node_deinit,
 940  	.ir_rate	= none_rate,
 941 +	.ir_rates	= none_rates,
 942  	.ir_tx_complete	= none_tx_complete,
 943  	.ir_tx_update	= none_tx_update,
 944  	.ir_setinterval	= none_setinterval,
 945 +	.ir_stats	= none_stats,
 946  };
 947  IEEE80211_RATECTL_MODULE(ratectl_none, 1);
 948  IEEE80211_RATECTL_ALG(none, IEEE80211_RATECTL_NONE, none);
 949 Index: sys/net80211/ieee80211_ratectl.c
 950 ===================================================================
 951 --- sys/net80211/ieee80211_ratectl.c	(revision 254826)
 952 +++ sys/net80211/ieee80211_ratectl.c	(working copy)
 953 @@ -1,5 +1,6 @@
 954  /*-
 955   * Copyright (c) 2010 Rui Paulo <rpaulo@FreeBSD.org>
 956 + * Copyright (c) 2013 Chenchong Qin <ccqin@FreeBSD.org>
 957   * All rights reserved.
 958   *
 959   * Redistribution and use in source and binary forms, with or without
 960 @@ -49,6 +50,40 @@
 961  
 962  MALLOC_DEFINE(M_80211_RATECTL, "80211ratectl", "802.11 rate control");
 963  
 964 +enum {
 965 +	MCS_HT20,
 966 +	MCS_HT20_SGI,
 967 +	MCS_HT40,
 968 +	MCS_HT40_SGI,
 969 +};
 970 +
 971 +int max_4ms_framelen[4][32] = {
 972 +	[MCS_HT20] = {
 973 +		3212,  6432,  9648,  12864,  19300,  25736,  28952,  32172,
 974 +		6424,  12852, 19280, 25708,  38568,  51424,  57852,  64280,
 975 +		9628,  19260, 28896, 38528,  57792,  65532,  65532,  65532,
 976 +		12828, 25656, 38488, 51320,  65532,  65532,  65532,  65532,
 977 +	},
 978 +	[MCS_HT20_SGI] = {
 979 +		3572,  7144,  10720,  14296,  21444,  28596,  32172,  35744,
 980 +		7140,  14284, 21428,  28568,  42856,  57144,  64288,  65532,
 981 +		10700, 21408, 32112,  42816,  64228,  65532,  65532,  65532,
 982 +		14256, 28516, 42780,  57040,  65532,  65532,  65532,  65532,
 983 +	},
 984 +	[MCS_HT40] = {
 985 +		6680,  13360,  20044,  26724,  40092,  53456,  60140,  65532,
 986 +		13348, 26700,  40052,  53400,  65532,  65532,  65532,  65532,
 987 +		20004, 40008,  60016,  65532,  65532,  65532,  65532,  65532,
 988 +		26644, 53292,  65532,  65532,  65532,  65532,  65532,  65532,
 989 +	},
 990 +	[MCS_HT40_SGI] = {
 991 +		7420,  14844,  22272,  29696,  44544,  59396,  65532,  65532,
 992 +		14832, 29668,  44504,  59340,  65532,  65532,  65532,  65532,
 993 +		22232, 44464,  65532,  65532,  65532,  65532,  65532,  65532,
 994 +		29616, 59232,  65532,  65532,  65532,  65532,  65532,  65532,
 995 +	}
 996 +};
 997 +
 998  void
 999  ieee80211_ratectl_register(int type, const struct ieee80211_ratectl *ratectl)
1000  {
1001 @@ -65,12 +100,36 @@
1002  	ratectls[type] = NULL;
1003  }
1004  
1005 +static int
1006 +ratectl_sysctl_stats(SYSCTL_HANDLER_ARGS)
1007 +{
1008 +	struct ieee80211vap *vap = arg1;
1009 +	int error, v;
1010 +
1011 +	v = 0;
1012 +	error = sysctl_handle_int(oidp, &v, 0, req);
1013 +	if (error || !req->newptr)
1014 +		return error;
1015 +
1016 +	ieee80211_ratectl_stats(vap);
1017 +	return 0;
1018 +}
1019 +
1020  void
1021 -ieee80211_ratectl_init(struct ieee80211vap *vap)
1022 +ieee80211_ratectl_init(struct ieee80211vap *vap, uint32_t capabilities)
1023  {
1024  	if (vap->iv_rate == ratectls[IEEE80211_RATECTL_NONE])
1025  		ieee80211_ratectl_set(vap, IEEE80211_RATECTL_AMRR);
1026 -	vap->iv_rate->ir_init(vap);
1027 +	vap->iv_rate->ir_init(vap, capabilities);
1028 +
1029 +	SYSCTL_ADD_PROC(vap->iv_sysctl, SYSCTL_CHILDREN(vap->iv_oid), 
1030 +			OID_AUTO, "ratectl_stats", CTLTYPE_INT | CTLFLAG_RW, 
1031 +			vap, 0, ratectl_sysctl_stats, "I", 
1032 +			"per-vap net80211 ratectl statistics");
1033 +
1034 +	IEEE80211_DPRINTF(vap, IEEE80211_MSG_RATECTL,
1035 +	    "%s: ratectl initialized. caps=0x%08x\n",
1036 +	    __func__, capabilities);
1037  }
1038  
1039  void
1040 @@ -90,3 +149,110 @@
1041  	}
1042  	vap->iv_rate = ratectls[type];
1043  }
1044 +
1045 +void
1046 +ieee80211_ratectl_complete_rcflags(struct ieee80211_node *ni,
1047 +		struct ieee80211_rc_info *rc_info)
1048 +{
1049 +	struct ieee80211vap *vap = ni->ni_vap;
1050 +	struct ieee80211_rc_series *rc = rc_info->iri_rc;
1051 +	const struct ieee80211_rate_table * rt = NULL;
1052 +	uint8_t rate;
1053 +	int i;
1054 +
1055 +	rt = ieee80211_get_ratetable(ni->ni_ic->ic_curchan);
1056 +
1057 +	/* Make sure that rate control code doesn't mess it up.
1058 +	 * If enable rts/cts and is pre-802.11n, blank tries 1, 2, 3 
1059 +	 */
1060 +
1061 +	if (! IEEE80211_RATECTL_HASCAP_MRRPROT(vap))
1062 +	{
1063 +		for (i = 1; i < IEEE80211_RATECTL_NUM; i++)
1064 +		{
1065 +			if (rc[0].flags & IEEE80211_RATECTL_FLAG_RTSCTS)
1066 +				rc[i].tries = 0;
1067 +			rc[i].flags &= ~IEEE80211_RATECTL_FLAG_RTSCTS; 
1068 +		}
1069 +	}
1070 +
1071 +	for (i = 0; i < IEEE80211_RATECTL_NUM; i++) {
1072 +		
1073 +		if (rc[i].tries == 0)
1074 +			continue;
1075 +
1076 +		rate = rt->info[rc[i].rix].dot11Rate;
1077 +
1078 +		/* Only enable dual-stream, shortgi, 2040 if HT is set */
1079 +
1080 +		if (IS_HT_RATE(rate)) {
1081 +			rc[i].flags |= IEEE80211_RATECTL_FLAG_HT;
1082 +
1083 +			if (ieee80211_ratectl_hascap_cw40(ni))
1084 +				rc[i].flags |= IEEE80211_RATECTL_FLAG_CW40;
1085 +
1086 +			if (ieee80211_ratectl_hascap_shortgi(ni))
1087 +				rc[i].flags |= IEEE80211_RATECTL_FLAG_SGI;
1088 +			/*
1089 +			 * If we have STBC TX enabled and the receiver
1090 +			 * can receive (at least) 1 stream STBC, AND it's
1091 +			 * MCS 0-7, AND we have at least two chains enabled,
1092 +			 * enable STBC.
1093 +			 */
1094 +			if (ieee80211_ratectl_hascap_stbc(ni) &&
1095 +				(rate & IEEE80211_RATE_VAL) < 8 &&
1096 +				HT_RC_2_STREAMS(rate) == 1)
1097 +				rc[i].flags |= IEEE80211_RATECTL_FLAG_STBC;
1098 +			
1099 +			/*
1100 +			 * Dual / Triple stream rate?
1101 +			 */
1102 +			if (HT_RC_2_STREAMS(rate) == 2)
1103 +				rc[i].flags |= IEEE80211_RATECTL_FLAG_DS;
1104 +			else if (HT_RC_2_STREAMS(rate) == 3)
1105 +				rc[i].flags |= IEEE80211_RATECTL_FLAG_TS;
1106 +
1107 +			/*
1108 +			 * Calculate the maximum 4ms frame length based
1109 +			 * on the MCS rate, SGI and channel width flags.
1110 +			 */
1111 +			if (HT_RC_2_MCS(rate) < 32) {
1112 +				int j;
1113 +				if (rc[i].flags & IEEE80211_RATECTL_FLAG_CW40) {
1114 +					if (rc[i].flags & IEEE80211_RATECTL_FLAG_SGI)
1115 +						j = MCS_HT40_SGI;
1116 +					else
1117 +						j = MCS_HT40;
1118 +				} else {
1119 +					if (rc[i].flags & IEEE80211_RATECTL_FLAG_SGI)
1120 +						j = MCS_HT20_SGI;
1121 +					else
1122 +						j = MCS_HT20;
1123 +				}
1124 +				rc[i].max4msframelen =
1125 +				    max_4ms_framelen[j][HT_RC_2_MCS(rate)];
1126 +			}
1127 +		} else {
1128 +			rc[i].max4msframelen = 0;
1129 +
1130 +			/*
1131 +			 * Only enable short preamble for legacy rates
1132 +			 */
1133 +			if (rc_info->iri_flags & IEEE80211_RATECTL_INFO_SP)
1134 +				rc[i].flags |= IEEE80211_RATECTL_FLAG_SP;
1135 +		}
1136 +
1137 +		/*
1138 +		 * Calculate the maximum TX power cap for the current
1139 +		 * node. 
1140 +		 * Rate control algo can't control TX power by now.
1141 +		 */
1142 +		rc[i].tx_power_cap = ieee80211_get_node_txpower(ni);
1143 +		
1144 +	}
1145 +	IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_RATECTL, ni,
1146 +	    "%s: flags: rc[0]:0x%08x, rc[1]:0x%08x, "
1147 +		"rc[2]:0x%08x, rc[3]:0x%08x\n", __func__, 
1148 +		rc[0].flags, rc[1].flags, rc[2].flags, rc[3].flags);
1149 +}
1150 +
1151 Index: sys/net80211/ieee80211_ratectl.h
1152 ===================================================================
1153 --- sys/net80211/ieee80211_ratectl.h	(revision 254826)
1154 +++ sys/net80211/ieee80211_ratectl.h	(working copy)
1155 @@ -1,5 +1,6 @@
1156  /*-
1157   * Copyright (c) 2010 Rui Paulo <rpaulo@FreeBSD.org>
1158 + * Copyright (c) 2013 Chenchong Qin <ccqin@FreeBSD.org>
1159   * All rights reserved.
1160   *
1161   * Redistribution and use in source and binary forms, with or without
1162 @@ -24,6 +25,8 @@
1163   *
1164   * $FreeBSD$
1165   */
1166 +#ifndef _NET80211_IEEE80211_RATECTL_H_
1167 +#define _NET80211_IEEE80211_RATECTL_H_
1168  
1169  enum ieee80211_ratealgs {
1170  	IEEE80211_RATECTL_AMRR		= 0,
1171 @@ -37,28 +40,115 @@
1172  #define	IEEE80211_RATECTL_TX_SUCCESS	1
1173  #define	IEEE80211_RATECTL_TX_FAILURE	0
1174  
1175 +#define	IEEE80211_RATECTL_TRUE		1
1176 +#define	IEEE80211_RATECTL_FALSE		0
1177 +
1178 +#define	IEEE80211_RATECTL_NUM		4
1179 +#define	IEEE80211_RATECTL_TXMAXTRY	11
1180 +
1181 +#define	IEEE80211_RATECTL_FLAG_DS		0x01	/* dual-stream rate */
1182 +#define	IEEE80211_RATECTL_FLAG_CW40		0x02	/* use HT40 */
1183 +#define	IEEE80211_RATECTL_FLAG_SGI		0x04	/* use short-GI */
1184 +#define	IEEE80211_RATECTL_FLAG_HT		0x08	/* use HT */
1185 +#define	IEEE80211_RATECTL_FLAG_RTSCTS	0x10	/* enable RTS/CTS protection */
1186 +#define	IEEE80211_RATECTL_FLAG_STBC		0x20	/* enable STBC */
1187 +#define	IEEE80211_RATECTL_FLAG_TS		0x40	/* triple-stream rate */
1188 +#define	IEEE80211_RATECTL_FLAG_SP		0x80	/* short preamble */
1189 +
1190 +/* Hardware CAPs offered to rate control algo */
1191 +#define	IEEE80211_RATECTL_CAP_MRR			0x01	/* support MRR */
1192 +#define	IEEE80211_RATECTL_CAP_MRRPROT		0x02	/* support MRR + protect */
1193 +#define	IEEE80211_RATECTL_CAP_MULTXCHAIN	0x04	/* has more than 1 txchain */
1194 +
1195 +#define IS_VAP_HT(vap)	((vap)->iv_htcaps & IEEE80211_HTC_HT)
1196 +#define IS_HT_RATE(_rate)   ((_rate) & 0x80)
1197 +#define HT_RC_2_MCS(_rc)    ((_rc) & 0x7f)
1198 +#define HT_RC_2_STREAMS(_rc)    ((((_rc) & 0x78) >> 3) + 1)
1199 +
1200 +extern int max_4ms_framelen[4][32];
1201 +
1202 +struct ieee80211_rc_series {
1203 +	uint8_t rix;		/* ratetable index, not rate code */
1204 +	uint8_t ratecode;	/* hardware rate code */
1205 +	uint8_t tries;
1206 +	uint8_t tx_power_cap;
1207 +	uint16_t flags;
1208 +	uint16_t max4msframelen;
1209 +};
1210 +
1211 +struct ieee80211_rc_info {
1212 +	struct ieee80211_rc_series iri_rc[IEEE80211_RATECTL_NUM];
1213 +	uint32_t iri_framelen;
1214 +	uint16_t iri_flags;			/* See below */
1215 +	uint16_t iri_maxaggrsize;	/* Maximum aggregate size */
1216 +
1217 +	/* TX info */
1218 +	uint8_t iri_txcnt;			/* TX count */
1219 +	uint8_t iri_failcnt;		/* TX retry-fail count */
1220 +	uint8_t iri_okcnt;			/* TX ok with or without retry */
1221 +	uint8_t iri_retrycnt;		/* TX retry count */
1222 +	uint8_t iri_shortretry;
1223 +	uint8_t iri_longretry;
1224 +	uint8_t iri_finaltsi;
1225 +	uint8_t iri_txrate;			/* HW tx rate */
1226 +};
1227 +
1228 +/* ieee80211_rc_info flags */
1229 +#define	IEEE80211_RATECTL_INFO_SP		0x01	/* short preamble */
1230 +#define	IEEE80211_RATECTL_INFO_AGGR		0x02	/* aggregation scenario */
1231 +
1232 +#define NET80211_TAG_RATECTL   1   /* net80211 ratectl state */
1233 +
1234 +/*
1235 + * net80211 ratectl statistics. 
1236 + * per vap ratectl seeting must start with this common state.
1237 + */
1238 +struct ieee80211_rc_stat {
1239 +	uint32_t irs_capabilities;		/* hardware capabilities offered to rc */
1240 +
1241 +	/* ratectl statistics */
1242 +	uint32_t irs_txcnt;
1243 +	uint32_t irs_failcnt;
1244 +	uint32_t irs_retrycnt;
1245 +	uint32_t irs_shortretry;
1246 +	uint32_t irs_longretry;
1247 +};
1248 +
1249 +#define IEEE80211_RATECTL_STAT(_vap) \
1250 +	((struct ieee80211_rc_stat *)((_vap)->iv_rs))
1251 +
1252 +#define	IEEE80211_RATECTL_HASCAP_MRR(_vap) \
1253 +	(IEEE80211_RATECTL_STAT(_vap)->irs_capabilities & IEEE80211_RATECTL_CAP_MRR)
1254 +#define	IEEE80211_RATECTL_HASCAP_MRRPROT(_vap) \
1255 +	(IEEE80211_RATECTL_STAT(_vap)->irs_capabilities & IEEE80211_RATECTL_CAP_MRRPROT)
1256 +#define	IEEE80211_RATECTL_HASCAP_MULTXCHAIN(_vap) \
1257 +	(IEEE80211_RATECTL_STAT(_vap)->irs_capabilities & IEEE80211_RATECTL_CAP_MULTXCHAIN)
1258 +
1259  struct ieee80211_ratectl {
1260  	const char *ir_name;
1261  	int	(*ir_attach)(const struct ieee80211vap *);
1262  	void	(*ir_detach)(const struct ieee80211vap *);
1263 -	void	(*ir_init)(struct ieee80211vap *);
1264 +	void	(*ir_init)(struct ieee80211vap *, uint32_t);
1265  	void	(*ir_deinit)(struct ieee80211vap *);
1266  	void	(*ir_node_init)(struct ieee80211_node *);
1267  	void	(*ir_node_deinit)(struct ieee80211_node *);
1268  	int	(*ir_rate)(struct ieee80211_node *, void *, uint32_t);
1269 +	void	(*ir_rates)(struct ieee80211_node *, struct ieee80211_rc_info *);
1270  	void	(*ir_tx_complete)(const struct ieee80211vap *,
1271 -	    			  const struct ieee80211_node *, int,
1272 -	    			  void *, void *);
1273 +	    			  const struct ieee80211_node *, struct ieee80211_rc_info *);
1274  	void	(*ir_tx_update)(const struct ieee80211vap *,
1275  	    			const struct ieee80211_node *,
1276  	    			void *, void *, void *);
1277  	void	(*ir_setinterval)(const struct ieee80211vap *, int);
1278 +	void	(*ir_stats)(const struct ieee80211vap *);
1279  };
1280  
1281  void	ieee80211_ratectl_register(int, const struct ieee80211_ratectl *);
1282  void	ieee80211_ratectl_unregister(int);
1283 -void	ieee80211_ratectl_init(struct ieee80211vap *);
1284 +void	ieee80211_ratectl_init(struct ieee80211vap *, uint32_t);
1285  void	ieee80211_ratectl_set(struct ieee80211vap *, int);
1286 +void	ieee80211_ratectl_complete_rcflags(struct ieee80211_node *, 
1287 +						struct ieee80211_rc_info*);
1288  
1289  MALLOC_DECLARE(M_80211_RATECTL);
1290  
1291 @@ -74,6 +164,8 @@
1292  	const struct ieee80211vap *vap = ni->ni_vap;
1293  
1294  	vap->iv_rate->ir_node_init(ni);
1295 +	IEEE80211_DPRINTF(vap, IEEE80211_MSG_RATECTL,
1296 +			"%s: net80211 ratectl node inited.\n", __func__);
1297  }
1298  
1299  static void __inline
1300 @@ -82,6 +174,8 @@
1301  	const struct ieee80211vap *vap = ni->ni_vap;
1302  
1303  	vap->iv_rate->ir_node_deinit(ni);
1304 +	IEEE80211_DPRINTF(vap, IEEE80211_MSG_RATECTL,
1305 +			"%s: net80211 ratectl node deinited.\n", __func__);
1306  }
1307  
1308  static int __inline
1309 @@ -93,10 +187,26 @@
1310  }
1311  
1312  static void __inline
1313 +ieee80211_ratectl_rates(struct ieee80211_node *ni, struct ieee80211_rc_info *rc_info)
1314 +{
1315 +	const struct ieee80211vap *vap = ni->ni_vap;
1316 +
1317 +	if (rc_info->iri_flags & IEEE80211_RATECTL_INFO_AGGR) 
1318 +		rc_info->iri_framelen = 0;
1319 +
1320 +	IEEE80211_DPRINTF(vap, IEEE80211_MSG_RATECTL,
1321 +			"%s: find rate sets for %saggregation scenario.\n", __func__, 
1322 +			(rc_info->iri_flags & IEEE80211_RATECTL_INFO_AGGR)? "" : "non-");
1323 +
1324 +	vap->iv_rate->ir_rates(ni, rc_info);
1325 +	ieee80211_ratectl_complete_rcflags(ni, rc_info);
1326 +}
1327 +
1328 +static void __inline
1329  ieee80211_ratectl_tx_complete(const struct ieee80211vap *vap,
1330 -    const struct ieee80211_node *ni, int status, void *arg1, void *arg2)
1331 +    const struct ieee80211_node *ni, struct ieee80211_rc_info *rc_info)
1332  {
1333 -	vap->iv_rate->ir_tx_complete(vap, ni, status, arg1, arg2);
1334 +	vap->iv_rate->ir_tx_complete(vap, ni, rc_info);
1335  }
1336  
1337  static void __inline
1338 @@ -115,3 +225,135 @@
1339  		return;
1340  	vap->iv_rate->ir_setinterval(vap, msecs);
1341  }
1342 +
1343 +static void __inline
1344 +ieee80211_ratectl_stats(const struct ieee80211vap *vap)
1345 +{
1346 +	printf("\n[%s]: net80211 ratectl statistics (%s)\n", 
1347 +			vap->iv_ifp->if_xname, vap->iv_rate->ir_name);
1348 +	if (vap->iv_rate->ir_stats == NULL)
1349 +		return;
1350 +	vap->iv_rate->ir_stats(vap);
1351 +}
1352 +
1353 +static int __inline
1354 +ieee80211_ratectl_hascap_cw40(const struct ieee80211_node *ni)
1355 +{
1356 +	return ni->ni_chw == 40;
1357 +}
1358 +
1359 +static int __inline
1360 +ieee80211_ratectl_hascap_shortgi(const struct ieee80211_node *ni)
1361 +{
1362 +	struct ieee80211com *ic = ni->ni_ic;
1363 +
1364 +	if (ni->ni_chw == 40 &&
1365 +		ic->ic_htcaps & IEEE80211_HTCAP_SHORTGI40 &&
1366 +		ni->ni_htcap & IEEE80211_HTCAP_SHORTGI40)
1367 +		return IEEE80211_RATECTL_TRUE;
1368 +
1369 +	if (ni->ni_chw == 20 &&
1370 +		ic->ic_htcaps & IEEE80211_HTCAP_SHORTGI20 &&
1371 +		ni->ni_htcap & IEEE80211_HTCAP_SHORTGI20)
1372 +		return IEEE80211_RATECTL_TRUE;
1373 +
1374 +	return IEEE80211_RATECTL_FALSE;
1375 +}
1376 +
1377 +static int __inline
1378 +ieee80211_ratectl_hascap_stbc(const struct ieee80211_node *ni)
1379 +{
1380 +	struct ieee80211com *ic = ni->ni_ic;
1381 +
1382 +	if (ic->ic_htcaps & IEEE80211_HTCAP_TXSTBC &&
1383 +		ni->ni_htcap & IEEE80211_HTCAP_RXSTBC_1STREAM &&
1384 +		IEEE80211_RATECTL_HASCAP_MULTXCHAIN(ni->ni_vap))
1385 +		return IEEE80211_RATECTL_TRUE;
1386 +	
1387 +	return IEEE80211_RATECTL_FALSE;
1388 +}
1389 +
1390 +static int __inline
1391 +ieee80211_ratectl_node_is11n(const struct ieee80211_node *ni)
1392 +{
1393 +	if (ni->ni_chan == NULL)
1394 +		return (0);
1395 +	if (ni->ni_chan == IEEE80211_CHAN_ANYC)
1396 +		return (0);
1397 +	return (IEEE80211_IS_CHAN_HT(ni->ni_chan));
1398 +}
1399 +
1400 +__inline static const struct ieee80211_rateset *
1401 +ieee80211_ratectl_get_rateset(const struct ieee80211_node *ni)
1402 +{
1403 +	const struct ieee80211_rateset *rs = NULL;
1404 +	/* 11n or not? Pick the right rateset */
1405 +	if (ieee80211_ratectl_node_is11n(ni)) {
1406 +		IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_RATECTL, ni,
1407 +				"%s: 11n node", __func__);
1408 +		rs = (struct ieee80211_rateset *) &ni->ni_htrates;
1409 +	} else {
1410 +		IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_RATECTL, ni,
1411 +			    "%s: non-11n node", __func__);
1412 +		rs = &ni->ni_rates;
1413 +	}
1414 +	return rs;
1415 +}
1416 +
1417 +static void __inline
1418 +ieee80211_ratectl_update_stat(const struct ieee80211vap *vap,
1419 +		const struct ieee80211_rc_info *rc_info)
1420 +{
1421 +	struct ieee80211_rc_stat * irs = IEEE80211_RATECTL_STAT(vap);
1422 +	irs->irs_txcnt += rc_info->iri_txcnt;
1423 +	irs->irs_failcnt += rc_info->iri_failcnt;
1424 +	irs->irs_retrycnt += rc_info->iri_retrycnt;
1425 +	irs->irs_shortretry += rc_info->iri_shortretry;
1426 +	irs->irs_longretry += rc_info->iri_longretry;
1427 +}
1428 +
1429 +static void __inline
1430 +ieee80211_ratectl_rc_info_set(struct ieee80211_rc_info *rc_info,
1431 +		uint8_t txcnt, uint8_t failcnt, uint32_t framelen,
1432 +		uint8_t shortretry, uint8_t longretry,
1433 +		uint8_t finaltsi, uint8_t txrate)
1434 +{
1435 +	rc_info->iri_txcnt = txcnt;
1436 +	rc_info->iri_failcnt = failcnt;
1437 +	rc_info->iri_okcnt = txcnt - failcnt;
1438 +	rc_info->iri_framelen = framelen;
1439 +	rc_info->iri_shortretry = shortretry;
1440 +	rc_info->iri_longretry = longretry;
1441 +	rc_info->iri_retrycnt = shortretry + longretry;
1442 +	rc_info->iri_finaltsi = finaltsi;
1443 +	rc_info->iri_txrate = txrate;
1444 +}
1445 +
1446 +__inline static struct ieee80211_rc_info *
1447 +ieee80211_ratectl_rc_info_get(struct ieee80211_node *ni,
1448 +		struct mbuf *m)
1449 +{
1450 +	struct m_tag *mtag;
1451 +
1452 +    mtag = m_tag_locate(m, MTAG_ABI_NET80211, 
1453 +			NET80211_TAG_RATECTL, NULL);
1454 +
1455 +	IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_RATECTL, ni,
1456 +			"%s: %sratectl mbuf tag found.\n", __func__, 
1457 +			(NULL == mtag? "no ":""));
1458 +again:
1459 +	if (NULL == mtag) {
1460 +		mtag = m_tag_alloc(MTAG_ABI_NET80211, NET80211_TAG_RATECTL,
1461 +				sizeof(struct ieee80211_rc_info), M_NOWAIT);
1462 +		if (NULL == mtag) {
1463 +			IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_RATECTL, ni,
1464 +					"%s: can't alloc mbuf tag for ratectl.\n", __func__);
1465 +			goto again;
1466 +		}
1467 +		bzero(mtag + 1, mtag->m_tag_len);
1468 +		m_tag_prepend(m, mtag);
1469 +	}
1470 +	return (struct ieee80211_rc_info*)(mtag + 1);
1471 +}
1472 +
1473 +#endif
1474 Index: sys/net80211/ieee80211_sample_txsched.h
1475 ===================================================================
1476 --- sys/net80211/ieee80211_sample_txsched.h	(revision 0)
1477 +++ sys/net80211/ieee80211_sample_txsched.h	(revision 257398)
1478 @@ -0,0 +1,241 @@
1479 +/* $FreeBSD: head/sys/dev/ath/ath_rate/sample/tx_schedules.h 240384 2012-08-15 07:50:42Z adrian $*/
1480 +
1481 +/*-
1482 + * Copyright (c) 2005 John Bicket
1483 + * Copyright (c) 2013 Chenchong Qin <ccqin@FreeBSD.org>
1484 + * All rights reserved.
1485 + *
1486 + * Redistribution and use in source and binary forms, with or without
1487 + * modification, are permitted provided that the following conditions
1488 + * are met:
1489 + * 1. Redistributions of source code must retain the above copyright
1490 + *    notice, this list of conditions and the following disclaimer,
1491 + *    without modification.
1492 + * 2. Redistributions in binary form must reproduce at minimum a disclaimer
1493 + *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
1494 + *    redistribution must be conditioned upon including a substantially
1495 + *    similar Disclaimer requirement for further binary redistribution.
1496 + * 3. Neither the names of the above-listed copyright holders nor the names
1497 + *    of any contributors may be used to endorse or promote products derived
1498 + *    from this software without specific prior written permission.
1499 + *
1500 + * Alternatively, this software may be distributed under the terms of the
1501 + * GNU General Public License ("GPL") version 2 as published by the Free
1502 + * Software Foundation.
1503 + *
1504 + * NO WARRANTY
1505 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1506 + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1507 + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
1508 + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
1509 + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
1510 + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
1511 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
1512 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
1513 + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
1514 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
1515 + * THE POSSIBILITY OF SUCH DAMAGES.
1516 + *
1517 + */
1518 +#ifndef	_NET80211_IEEE80211_RATECTL_SAMPLE_TXSCHEDULES_H_
1519 +#define	_NET80211_IEEE80211_RATECTL_SAMPLE_TXSCHEDULES_H_
1520 +
1521 +#include <sys/cdefs.h>
1522 +
1523 +#define A(_r) \
1524 +    (((_r) == 6)   ? 0 : (((_r) == 9)   ? 1 : (((_r) == 12)  ? 2 : \
1525 +    (((_r) == 18)  ? 3 : (((_r) == 24)  ? 4 : (((_r) == 36)  ? 5 : \
1526 +    (((_r) == 48)  ? 6 : (((_r) == 54)  ? 7 : 0))))))))
1527 +static const struct txschedule series_11a[] = {
1528 +	{ 3,A( 6), 3,A(  6), 0,A(  6), 0,A( 6) },	/*   6Mb/s */
1529 +	{ 4,A( 9), 3,A(  6), 4,A(  6), 0,A( 6) },	/*   9Mb/s */
1530 +	{ 4,A(12), 3,A(  6), 4,A(  6), 0,A( 6) },	/*  12Mb/s */
1531 +	{ 4,A(18), 3,A( 12), 4,A(  6), 2,A( 6) },	/*  18Mb/s */
1532 +	{ 4,A(24), 3,A( 18), 4,A( 12), 2,A( 6) },	/*  24Mb/s */
1533 +	{ 4,A(36), 3,A( 24), 4,A( 18), 2,A( 6) },	/*  36Mb/s */
1534 +	{ 4,A(48), 3,A( 36), 4,A( 24), 2,A(12) },	/*  48Mb/s */
1535 +	{ 4,A(54), 3,A( 48), 4,A( 36), 2,A(24) }	/*  54Mb/s */
1536 +};
1537 +
1538 +#define NA1(_r) \
1539 +	(((_r) == 6.5)  ? 8 : (((_r) == 13)  ?  9 : (((_r) == 19.5)? 10 : \
1540 +	(((_r) == 26)  ? 11 : (((_r) == 39)  ? 12 : (((_r) == 52)  ? 13 : \
1541 +	(((_r) == 58.5)? 14 : (((_r) == 65)  ? 15 : 0))))))))
1542 +#define NA2(_r) \
1543 +	(((_r) == 13) ? 16 : (((_r) == 26) ? 17 : (((_r) == 39) ? 18 : \
1544 +	(((_r) == 52) ? 19 : (((_r) == 78) ? 20 : (((_r) == 104)? 21 : \
1545 +	(((_r) == 117)? 22 : (((_r) == 130)? 23 : 0))))))))
1546 +#define NA3(_r) \
1547 +	(((_r) == 19.5)  ? 24 : (((_r) == 39) ? 25 : (((_r) == 58.5)  ? 26 : \
1548 +	(((_r) == 78)  ? 27 : (((_r) == 117) ? 28 : (((_r) == 156) ? 29 : \
1549 +	(((_r) == 175.5) ? 30 : (((_r) == 195)? 31 : 0))))))))
1550 +static const struct txschedule series_11na[] = {
1551 +	{ 3,A( 6), 3,A(  6), 0,A(  6), 0,A( 6) },       /*   6Mb/s */
1552 +	{ 4,A( 9), 3,A(  6), 4,A(  6), 0,A( 6) },       /*   9Mb/s */
1553 +	{ 4,A(12), 3,A(  6), 4,A(  6), 0,A( 6) },       /*  12Mb/s */
1554 +	{ 4,A(18), 3,A( 12), 4,A(  6), 2,A( 6) },       /*  18Mb/s */
1555 +	{ 4,A(24), 3,A( 18), 4,A( 12), 2,A( 6) },       /*  24Mb/s */
1556 +	{ 4,A(36), 3,A( 24), 4,A( 18), 2,A( 6) },       /*  36Mb/s */
1557 +	{ 4,A(48), 3,A( 36), 4,A( 24), 2,A(12) },       /*  48Mb/s */
1558 +	{ 4,A(54), 3,A( 48), 4,A( 36), 2,A(24) },       /*  54Mb/s */
1559 +
1560 +	/* 1 stream rates */
1561 +
1562 +	{ 3,NA1( 6.5), 3,NA1( 6.5), 0,NA1( 6.5), 0,NA1(6.5) },  /* 6.5Mb/s */
1563 +	{ 4,NA1(  13), 3,NA1( 6.5), 4,NA1( 6.5), 0,NA1(6.5) },  /*  13Mb/s */
1564 +	{ 4,NA1(19.5), 3,NA1( 6.5), 4,NA1( 6.5), 0,NA1(6.5) },  /*19.5Mb/s */
1565 +	{ 4,NA1(  26), 3,NA1(19.5), 4,NA1( 6.5), 2,NA1(6.5) },  /*  26Mb/s */
1566 +	{ 4,NA1(  39), 3,NA1(  26), 4,NA1(19.5), 2,NA1(6.5) },  /*  39Mb/s */
1567 +	{ 4,NA1(  52), 3,NA1(  39), 4,NA1(  26), 2,NA1(6.5) },  /*  52Mb/s */
1568 +	{ 4,NA1(58.5), 3,NA1(  52), 4,NA1(  39), 2,NA1( 13) },  /*58.5Mb/s */
1569 +	{ 4,NA1(  65), 3,NA1(58.5), 4,NA1(  52), 2,NA1( 13) },  /*  65Mb/s */
1570 +
1571 +	/* 2 stream rates */
1572 +
1573 +	{ 3,NA2(  13), 3,NA2(  13), 0,NA2(  13), 0,NA2( 13) },  /*  13Mb/s */
1574 +	{ 4,NA2(  26), 3,NA2(  13), 4,NA2(  13), 0,NA2( 13) },  /*  26Mb/s */
1575 +	{ 4,NA2(  39), 3,NA2(  26), 4,NA2(  13), 2,NA2( 13) },  /*  39Mb/s */
1576 +	{ 4,NA2(  52), 3,NA2(  39), 4,NA2(  26), 2,NA2( 13) },  /*  52Mb/s */
1577 +	{ 4,NA2(  78), 3,NA2(  52), 4,NA2(  39), 2,NA2( 13) },  /*  78Mb/s */
1578 +	{ 4,NA2( 104), 3,NA2(  78), 4,NA2(  52), 2,NA2( 13) },  /* 104Mb/s */
1579 +	{ 4,NA2( 117), 3,NA2( 104), 4,NA2(  78), 2,NA2( 26) },  /* 117Mb/s */
1580 +	{ 4,NA2( 130), 3,NA2( 117), 4,NA2( 104), 2,NA2( 26) },   /* 130Mb/s */
1581 +
1582 +	/* 3 stream rates */
1583 +
1584 +	{ 3,NA3(19.5), 3,NA3(19.5), 0,NA3(19.5), 0,NA3(19.5) },  /*  19Mb/s */
1585 +	{ 3,NA3(  39), 3,NA3(19.5), 0,NA3(19.5), 0,NA3(19.5) },  /*  39Mb/s */
1586 +	{ 3,NA3(58.5), 3,NA3(  39), 0,NA3(19.5), 0,NA3(19.5) },  /*  58Mb/s */
1587 +	{ 3,NA3(  78), 3,NA3(58.5), 0,NA3(  39), 0,NA3(19.5) },  /*  78Mb/s */
1588 +	{ 3,NA3( 117), 3,NA3(  78), 0,NA3(58.5), 0,NA3(19.5) },  /* 117Mb/s */
1589 +	{ 3,NA3( 156), 3,NA3( 117), 0,NA3(  78), 0,NA3(19.5) },  /*  156Mb/s */
1590 +	{ 3,NA3(175.5), 3,NA3( 156), 0,NA3( 117), 0,NA3(  39) },  /*  175Mb/s */
1591 +	{ 3,NA3( 195), 3,NA3( 195), 0,NA3( 156), 0,NA3(58.5) },  /* 195Mb/s */
1592 +};
1593 +#undef A
1594 +#undef NA3
1595 +#undef NA2
1596 +#undef NA1
1597 +
1598 +#define G(_r) \
1599 +    (((_r) == 1)   ? 0 : (((_r) == 2)   ? 1 : (((_r) == 5.5) ? 2 : \
1600 +    (((_r) == 11)  ? 3 : (((_r) == 6)   ? 4 : (((_r) == 9)   ? 5 : \
1601 +    (((_r) == 12)  ? 6 : (((_r) == 18)  ? 7 : (((_r) == 24)  ? 8 : \
1602 +    (((_r) == 36)  ? 9 : (((_r) == 48)  ? 10 : (((_r) == 54)  ? 11 : 0))))))))))))
1603 +static const struct txschedule series_11g[] = {
1604 +	{ 3,G( 1), 3,G(  1), 0,G(  1), 0,G( 1) },	/*   1Mb/s */
1605 +	{ 4,G( 2), 3,G(  1), 4,G(  1), 0,G( 1) },	/*   2Mb/s */
1606 +	{ 4,G(5.5),3,G(  2), 4,G(  1), 2,G( 1) },	/* 5.5Mb/s */
1607 +	{ 4,G(11), 3,G(5.5), 4,G(  2), 2,G( 1) },	/*  11Mb/s */
1608 +	{ 4,G( 6), 3,G(5.5), 4,G(  2), 2,G( 1) },	/*   6Mb/s */
1609 +	{ 4,G( 9), 3,G(  6), 4,G(5.5), 2,G( 1) },	/*   9Mb/s */
1610 +	{ 4,G(12), 3,G( 11), 4,G(5.5), 2,G( 1) },	/*  12Mb/s */
1611 +	{ 4,G(18), 3,G( 12), 4,G( 11), 2,G( 1) },	/*  18Mb/s */
1612 +	{ 4,G(24), 3,G( 18), 4,G( 12), 2,G( 1) },	/*  24Mb/s */
1613 +	{ 4,G(36), 3,G( 24), 4,G( 18), 2,G( 1) },	/*  36Mb/s */
1614 +	{ 4,G(48), 3,G( 36), 4,G( 24), 2,G( 1) },	/*  48Mb/s */
1615 +	{ 4,G(54), 3,G( 48), 4,G( 36), 2,G( 1) }	/*  54Mb/s */
1616 +};
1617 +
1618 +#define NG1(_r) \
1619 +	(((_r) == 6.5) ? 12 : (((_r) == 13) ? 13 : (((_r) == 19.5)? 14 : \
1620 +	(((_r) == 26)  ? 15 : (((_r) == 39) ? 16 : (((_r) == 52)  ? 17 : \
1621 +	(((_r) == 58.5)? 18 : (((_r) == 65) ? 19 : 0))))))))
1622 +#define NG2(_r) \
1623 +	(((_r) == 13)  ? 20 : (((_r) == 26) ? 21 : (((_r) == 39)  ? 22 : \
1624 +	(((_r) == 52)  ? 23 : (((_r) == 78) ? 24 : (((_r) == 104) ? 25 : \
1625 +	(((_r) == 117) ? 26 : (((_r) == 130)? 27 : 0))))))))
1626 +#define NG3(_r) \
1627 +	(((_r) == 19.5)  ? 28 : (((_r) == 39) ? 29 : (((_r) == 58.5)  ? 30 : \
1628 +	(((_r) == 78)  ? 31 : (((_r) == 117) ? 32 : (((_r) == 156) ? 33 : \
1629 +	(((_r) == 175.5) ? 34 : (((_r) == 195)? 35 : 0))))))))
1630 +
1631 +static const struct txschedule series_11ng[] = {
1632 +	{ 3,G( 1), 3,G(  1), 0,G(  1), 0,G( 1) },       /*   1Mb/s */
1633 +	{ 4,G( 2), 3,G(  1), 4,G(  1), 0,G( 1) },       /*   2Mb/s */
1634 +	{ 4,G(5.5),3,G(  2), 4,G(  1), 2,G( 1) },       /* 5.5Mb/s */
1635 +	{ 4,G(11), 3,G(5.5), 4,G(  2), 2,G( 1) },       /*  11Mb/s */
1636 +	{ 4,G( 6), 3,G(5.5), 4,G(  2), 2,G( 1) },       /*   6Mb/s */
1637 +	{ 4,G( 9), 3,G(  6), 4,G(5.5), 2,G( 1) },       /*   9Mb/s */
1638 +	{ 4,G(12), 3,G( 11), 4,G(5.5), 2,G( 1) },       /*  12Mb/s */
1639 +	{ 4,G(18), 3,G( 12), 4,G( 11), 2,G( 1) },       /*  18Mb/s */
1640 +	{ 4,G(24), 3,G( 18), 4,G( 12), 2,G( 1) },       /*  24Mb/s */
1641 +	{ 4,G(36), 3,G( 24), 4,G( 18), 2,G( 1) },       /*  36Mb/s */
1642 +	{ 4,G(48), 3,G( 36), 4,G( 24), 2,G( 1) },       /*  48Mb/s */
1643 +	{ 4,G(54), 3,G( 48), 4,G( 36), 2,G( 1) },       /*  54Mb/s */
1644 +
1645 +	/* 1 stream rates */
1646 +
1647 +	{ 3,NG1( 6.5), 3,NG1( 6.5), 0,NG1( 6.5), 0,NG1(6.5) },  /* 6.5Mb/s */
1648 +	{ 4,NG1(  13), 3,NG1( 6.5), 4,NG1( 6.5), 0,NG1(6.5) },  /*  13Mb/s */
1649 +	{ 4,NG1(19.5), 3,NG1( 6.5), 4,NG1( 6.5), 0,NG1(6.5) },  /*19.5Mb/s */
1650 +	{ 4,NG1(  26), 3,NG1(19.5), 4,NG1( 6.5), 2,NG1(6.5) },  /*  26Mb/s */
1651 +	{ 4,NG1(  39), 3,NG1(  26), 4,NG1(19.5), 2,NG1(6.5) },  /*  39Mb/s */
1652 +	{ 4,NG1(  52), 3,NG1(  39), 4,NG1(  26), 2,NG1(6.5) },  /*  52Mb/s */
1653 +	{ 4,NG1(58.5), 3,NG1(  52), 4,NG1(  39), 2,NG1( 13) },  /*58.5Mb/s */
1654 +	{ 4,NG1(  65), 3,NG1(58.5), 4,NG1(  52), 2,NG1( 13) },  /*  65Mb/s */
1655 +
1656 +	/* 2 stream rates */
1657 +
1658 +	{ 3,NG2(  13), 3,NG2(  13), 0,NG2(  13), 0,NG2( 13) },  /*  13Mb/s */
1659 +	{ 4,NG2(  26), 3,NG2(  13), 4,NG2(  13), 0,NG2( 13) },  /*  26Mb/s */
1660 +	{ 4,NG2(  39), 3,NG2(  26), 4,NG2(  13), 2,NG2( 13) },  /*  39Mb/s */
1661 +	{ 4,NG2(  52), 3,NG2(  39), 4,NG2(  26), 2,NG2( 13) },  /*  52Mb/s */
1662 +	{ 4,NG2(  78), 3,NG2(  52), 4,NG2(  39), 2,NG2( 13) },  /*  78Mb/s */
1663 +	{ 4,NG2( 104), 3,NG2(  78), 4,NG2(  52), 2,NG2( 13) },  /* 104Mb/s */
1664 +	{ 4,NG2( 117), 3,NG2( 104), 4,NG2(  78), 2,NG2( 26) },  /* 117Mb/s */
1665 +	{ 4,NG2( 130), 3,NG2( 117), 4,NG2( 104), 2,NG2( 26) },  /* 130Mb/s */
1666 +
1667 +	/* 3 stream rates */
1668 +
1669 +	{ 3,NG3(19.5), 3,NG3(19.5), 0,NG3(19.5), 0,NG3(19.5) },  /*  19Mb/s */
1670 +	{ 3,NG3(  39), 3,NG3(19.5), 0,NG3(19.5), 0,NG3(19.5) },  /*  39Mb/s */
1671 +	{ 3,NG3(58.5), 3,NG3(  39), 0,NG3(19.5), 0,NG3(19.5) },  /*  58Mb/s */
1672 +	{ 3,NG3(  78), 3,NG3(58.5), 0,NG3(  39), 0,NG3(19.5) },  /*  78Mb/s */
1673 +	{ 3,NG3( 117), 3,NG3(  78), 0,NG3(58.5), 0,NG3(19.5) },  /* 117Mb/s */
1674 +	{ 3,NG3( 156), 3,NG3( 117), 0,NG3(  78), 0,NG3(19.5) },  /*  156Mb/s */
1675 +	{ 3,NG3(175.5), 3,NG3( 156), 0,NG3( 117), 0,NG3(  39) },  /*  175Mb/s */
1676 +	{ 3,NG3( 195), 3,NG3( 195), 0,NG3( 156), 0,NG3(58.5) },  /* 195Mb/s */
1677 +
1678 +};
1679 +#undef G
1680 +#undef NG3
1681 +#undef NG2
1682 +#undef NG1
1683 +
1684 +#define H(_r) \
1685 +    (((_r) == 3)   ? 0 : (((_r) == 4.5) ? 1 : (((_r) == 6)  ? 2 : \
1686 +    (((_r) == 9)   ? 3 : (((_r) == 12)  ? 4 : (((_r) == 18) ? 5 : \
1687 +    (((_r) == 24)  ? 6 : (((_r) == 27)  ? 7 : 0))))))))
1688 +static const struct txschedule series_half[] = {
1689 +	{ 3,H( 3), 3,H(  3), 0,H(  3), 0,H( 3) },	/*   3Mb/s */
1690 +	{ 4,H(4.5),3,H(  3), 4,H(  3), 0,H( 3) },	/* 4.5Mb/s */
1691 +	{ 4,H( 6), 3,H(  3), 4,H(  3), 0,H( 3) },	/*   6Mb/s */
1692 +	{ 4,H( 9), 3,H(  6), 4,H(  3), 2,H( 3) },	/*   9Mb/s */
1693 +	{ 4,H(12), 3,H(  9), 4,H(  6), 2,H( 3) },	/*  12Mb/s */
1694 +	{ 4,H(18), 3,H( 12), 4,H(  9), 2,H( 3) },	/*  18Mb/s */
1695 +	{ 4,H(24), 3,H( 18), 4,H( 12), 2,H( 6) },	/*  24Mb/s */
1696 +	{ 4,H(27), 3,H( 24), 4,H( 18), 2,H(12) }	/*  27Mb/s */
1697 +};
1698 +#undef H
1699 +
1700 +#ifdef Q
1701 +#undef Q
1702 +#endif
1703 +#define Q(_r) \
1704 +    (((_r) == 1.5) ? 0 : (((_r) ==2.25) ? 1 : (((_r) == 3)  ? 2 : \
1705 +    (((_r) == 4.5) ? 3 : (((_r) ==  6)  ? 4 : (((_r) == 9)  ? 5 : \
1706 +    (((_r) == 12)  ? 6 : (((_r) == 13.5)? 7 : 0))))))))
1707 +static const struct txschedule series_quarter[] = {
1708 +	{ 3,Q( 1.5),3,Q(1.5), 0,Q(1.5), 0,Q(1.5) },	/* 1.5Mb/s */
1709 +	{ 4,Q(2.25),3,Q(1.5), 4,Q(1.5), 0,Q(1.5) },	/*2.25Mb/s */
1710 +	{ 4,Q(   3),3,Q(1.5), 4,Q(1.5), 0,Q(1.5) },	/*   3Mb/s */
1711 +	{ 4,Q( 4.5),3,Q(  3), 4,Q(1.5), 2,Q(1.5) },	/* 4.5Mb/s */
1712 +	{ 4,Q(   6),3,Q(4.5), 4,Q(  3), 2,Q(1.5) },	/*   6Mb/s */
1713 +	{ 4,Q(   9),3,Q(  6), 4,Q(4.5), 2,Q(1.5) },	/*   9Mb/s */
1714 +	{ 4,Q(  12),3,Q(  9), 4,Q(  6), 2,Q(  3) },	/*  12Mb/s */
1715 +	{ 4,Q(13.5),3,Q( 12), 4,Q(  9), 2,Q(  6) }	/*13.5Mb/s */
1716 +};
1717 +#undef Q
1718 +
1719 +#endif /* _NET80211_IEEE80211_RATECTL_SAMPLE_TXSCHEDULES_H_ */
1720 Index: sys/net80211/ieee80211_rssadapt.c
1721 ===================================================================
1722 --- sys/net80211/ieee80211_rssadapt.c	(revision 254826)
1723 +++ sys/net80211/ieee80211_rssadapt.c	(working copy)
1724 @@ -74,7 +74,7 @@
1725  				    parm##_denom)
1726  
1727  static void	rssadapt_setinterval(const struct ieee80211vap *, int);
1728 -static void	rssadapt_init(struct ieee80211vap *);
1729 +static void	rssadapt_init(struct ieee80211vap *, uint32_t);
1730  static void	rssadapt_deinit(struct ieee80211vap *);
1731  static void	rssadapt_updatestats(struct ieee80211_rssadapt_node *);
1732  static void	rssadapt_node_init(struct ieee80211_node *);
1733 @@ -84,8 +84,7 @@
1734  static void	rssadapt_raise_rate(struct ieee80211_rssadapt_node *,
1735  			int, int);
1736  static void	rssadapt_tx_complete(const struct ieee80211vap *,
1737 -    			const struct ieee80211_node *, int,
1738 -			void *, void *);
1739 +    			const struct ieee80211_node *, struct ieee80211_rc_info *);
1740  static void	rssadapt_sysctlattach(struct ieee80211vap *,
1741  			struct sysctl_ctx_list *, struct sysctl_oid *);
1742  
1743 @@ -121,7 +120,7 @@
1744  }
1745  
1746  static void
1747 -rssadapt_init(struct ieee80211vap *vap)
1748 +rssadapt_init(struct ieee80211vap *vap, uint32_t capabilities)
1749  {
1750  	struct ieee80211_rssadapt *rs;
1751  
1752 @@ -134,6 +133,10 @@
1753  		if_printf(vap->iv_ifp, "couldn't alloc ratectl structure\n");
1754  		return;
1755  	}
1756 +
1757 +	struct ieee80211_rc_stat * irs = IEEE80211_RATECTL_STAT(vap);
1758 +	irs->irs_capabilities = capabilities;
1759 +
1760  	rs->vap = vap;
1761  	rssadapt_setinterval(vap, 500 /* msecs */);
1762  	rssadapt_sysctlattach(vap, vap->iv_sysctl, vap->iv_oid);
1763 @@ -307,10 +310,11 @@
1764  
1765  static void
1766  rssadapt_tx_complete(const struct ieee80211vap *vap,
1767 -    const struct ieee80211_node *ni, int success, void *arg1, void *arg2)
1768 +    const struct ieee80211_node *ni, struct ieee80211_rc_info *rc_info)
1769  {
1770  	struct ieee80211_rssadapt_node *ra = ni->ni_rctls;
1771 -	int pktlen = *(int *)arg1, rssi = *(int *)arg2;
1772 +	/*int pktlen = *(int *)arg1, rssi = *(int *)arg2;*/
1773 +	int pktlen = 0, rssi = 0, success = 0; /* just make it compiled. qcc */
1774  
1775  	if (success) {
1776  		ra->ra_nok++;
1777 Index: sys/net80211/ieee80211_amrr.c
1778 ===================================================================
1779 --- sys/net80211/ieee80211_amrr.c	(revision 254826)
1780 +++ sys/net80211/ieee80211_amrr.c	(working copy)
1781 @@ -47,8 +47,8 @@
1782  
1783  #include <net80211/ieee80211_var.h>
1784  #include <net80211/ieee80211_ht.h>
1785 +#include <net80211/ieee80211_ratectl.h>
1786  #include <net80211/ieee80211_amrr.h>
1787 -#include <net80211/ieee80211_ratectl.h>
1788  
1789  #define is_success(amn)	\
1790  	((amn)->amn_retrycnt < (amn)->amn_txcnt / 10)
1791 @@ -57,19 +57,18 @@
1792  #define is_enough(amn)		\
1793  	((amn)->amn_txcnt > 10)
1794  
1795 -static void	amrr_setinterval(const struct ieee80211vap *, int);
1796 -static void	amrr_init(struct ieee80211vap *);
1797 +static void	amrr_init(struct ieee80211vap *, uint32_t);
1798  static void	amrr_deinit(struct ieee80211vap *);
1799  static void	amrr_node_init(struct ieee80211_node *);
1800  static void	amrr_node_deinit(struct ieee80211_node *);
1801 -static int	amrr_update(struct ieee80211_amrr *,
1802 -    			struct ieee80211_amrr_node *, struct ieee80211_node *);
1803  static int	amrr_rate(struct ieee80211_node *, void *, uint32_t);
1804 +static void	amrr_rates(struct ieee80211_node *, struct ieee80211_rc_info *);
1805  static void	amrr_tx_complete(const struct ieee80211vap *,
1806 -    			const struct ieee80211_node *, int, 
1807 -			void *, void *);
1808 -static void	amrr_tx_update(const struct ieee80211vap *vap,
1809 +    			const struct ieee80211_node *, struct ieee80211_rc_info *);
1810 +static void	amrr_tx_update(const struct ieee80211vap *,
1811  			const struct ieee80211_node *, void *, void *, void *);
1812 +static void	amrr_stats(const struct ieee80211vap *);
1813 +static void	amrr_setinterval(const struct ieee80211vap *, int);
1814  static void	amrr_sysctlattach(struct ieee80211vap *,
1815  			struct sysctl_ctx_list *, struct sysctl_oid *);
1816  
1817 @@ -85,9 +84,11 @@
1818  	.ir_node_init	= amrr_node_init,
1819  	.ir_node_deinit	= amrr_node_deinit,
1820  	.ir_rate	= amrr_rate,
1821 +	.ir_rates	= amrr_rates,
1822  	.ir_tx_complete	= amrr_tx_complete,
1823  	.ir_tx_update	= amrr_tx_update,
1824  	.ir_setinterval	= amrr_setinterval,
1825 +	.ir_stats	= amrr_stats,
1826  };
1827  IEEE80211_RATECTL_MODULE(amrr, 1);
1828  IEEE80211_RATECTL_ALG(amrr, IEEE80211_RATECTL_AMRR, amrr);
1829 @@ -105,7 +106,7 @@
1830  }
1831  
1832  static void
1833 -amrr_init(struct ieee80211vap *vap)
1834 +amrr_init(struct ieee80211vap *vap, uint32_t capabilities)
1835  {
1836  	struct ieee80211_amrr *amrr;
1837  
1838 @@ -117,6 +118,10 @@
1839  		if_printf(vap->iv_ifp, "couldn't alloc ratectl structure\n");
1840  		return;
1841  	}
1842 +
1843 +	struct ieee80211_rc_stat * irs = IEEE80211_RATECTL_STAT(vap);
1844 +	irs->irs_capabilities = capabilities;
1845 +
1846  	amrr->amrr_min_success_threshold = IEEE80211_AMRR_MIN_SUCCESS_THRESHOLD;
1847  	amrr->amrr_max_success_threshold = IEEE80211_AMRR_MAX_SUCCESS_THRESHOLD;
1848  	amrr_setinterval(vap, 500 /* ms */);
1849 @@ -129,17 +134,6 @@
1850  	free(vap->iv_rs, M_80211_RATECTL);
1851  }
1852  
1853 -static int
1854 -amrr_node_is_11n(struct ieee80211_node *ni)
1855 -{
1856 -
1857 -	if (ni->ni_chan == NULL)
1858 -		return (0);
1859 -	if (ni->ni_chan == IEEE80211_CHAN_ANYC)
1860 -		return (0);
1861 -	return (IEEE80211_IS_CHAN_HT(ni->ni_chan));
1862 -}
1863 -
1864  static void
1865  amrr_node_init(struct ieee80211_node *ni)
1866  {
1867 @@ -159,29 +153,20 @@
1868  		}
1869  	} else
1870  		amn = ni->ni_rctls;
1871 +
1872  	amn->amn_amrr = amrr;
1873  	amn->amn_success = 0;
1874  	amn->amn_recovery = 0;
1875  	amn->amn_txcnt = amn->amn_retrycnt = 0;
1876  	amn->amn_success_threshold = amrr->amrr_min_success_threshold;
1877  
1878 -	/* 11n or not? Pick the right rateset */
1879 -	if (amrr_node_is_11n(ni)) {
1880 -		/* XXX ew */
1881 -		IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_RATECTL, ni,
1882 -		    "%s: 11n node", __func__);
1883 -		rs = (struct ieee80211_rateset *) &ni->ni_htrates;
1884 -	} else {
1885 -		IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_RATECTL, ni,
1886 -		    "%s: non-11n node", __func__);
1887 -		rs = &ni->ni_rates;
1888 -	}
1889 +	rs = ieee80211_ratectl_get_rateset(ni);
1890  
1891  	/* Initial rate - lowest */
1892  	rate = rs->rs_rates[0];
1893  
1894  	/* XXX clear the basic rate flag if it's not 11n */
1895 -	if (! amrr_node_is_11n(ni))
1896 +	if (! ieee80211_ratectl_node_is11n(ni))
1897  		rate &= IEEE80211_RATE_VAL;
1898  
1899  	/* pick initial rate from the rateset - HT or otherwise */
1900 @@ -189,7 +174,7 @@
1901  	    amn->amn_rix--) {
1902  		/* legacy - anything < 36mbit, stop searching */
1903  		/* 11n - stop at MCS4 / MCS12 / MCS28 */
1904 -		if (amrr_node_is_11n(ni) &&
1905 +		if (ieee80211_ratectl_node_is11n(ni) &&
1906  		    (rs->rs_rates[amn->amn_rix] & 0x7) < 4)
1907  			break;
1908  		else if ((rs->rs_rates[amn->amn_rix] & IEEE80211_RATE_VAL) <= 72)
1909 @@ -198,7 +183,7 @@
1910  	}
1911  
1912  	/* if the rate is an 11n rate, ensure the MCS bit is set */
1913 -	if (amrr_node_is_11n(ni))
1914 +	if (ieee80211_ratectl_node_is11n(ni))
1915  		rate |= IEEE80211_RATE_MCS;
1916  
1917  	/* Assign initial rate from the rateset */
1918 @@ -206,9 +191,8 @@
1919  	amn->amn_ticks = ticks;
1920  
1921  	IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_RATECTL, ni,
1922 -	    "AMRR: nrates=%d, initial rate %d",
1923 -	    rs->rs_nrates,
1924 -	    rate);
1925 +	    "%s: AMRR: nrates=%d, initial rate %d",
1926 +		__func__, rs->rs_nrates, rate);
1927  }
1928  
1929  static void
1930 @@ -226,17 +210,12 @@
1931  
1932  	KASSERT(is_enough(amn), ("txcnt %d", amn->amn_txcnt));
1933  
1934 -	/* 11n or not? Pick the right rateset */
1935 -	if (amrr_node_is_11n(ni)) {
1936 -		/* XXX ew */
1937 -		rs = (struct ieee80211_rateset *) &ni->ni_htrates;
1938 -	} else {
1939 -		rs = &ni->ni_rates;
1940 -	}
1941 +	rs = ieee80211_ratectl_get_rateset(ni);
1942  
1943 +
1944  	IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_RATECTL, ni,
1945 -	    "AMRR: current rate %d, txcnt=%d, retrycnt=%d",
1946 -	    rs->rs_rates[rix] & IEEE80211_RATE_VAL,
1947 +	    "%s: AMRR: current rate %d, txcnt=%d, retrycnt=%d",
1948 +	    __func__, rs->rs_rates[rix] & IEEE80211_RATE_VAL,
1949  	    amn->amn_txcnt,
1950  	    amn->amn_retrycnt);
1951  
1952 @@ -256,8 +235,8 @@
1953  			amn->amn_success = 0;
1954  			rix++;
1955  			IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_RATECTL, ni,
1956 -			    "AMRR increasing rate %d (txcnt=%d retrycnt=%d)",
1957 -			    rs->rs_rates[rix] & IEEE80211_RATE_VAL,
1958 +			    "%s: AMRR increasing rate %d (txcnt=%d retrycnt=%d)",
1959 +			    __func__, rs->rs_rates[rix] & IEEE80211_RATE_VAL,
1960  			    amn->amn_txcnt, amn->amn_retrycnt);
1961  		} else {
1962  			amn->amn_recovery = 0;
1963 @@ -277,8 +256,8 @@
1964  			}
1965  			rix--;
1966  			IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_RATECTL, ni,
1967 -			    "AMRR decreasing rate %d (txcnt=%d retrycnt=%d)",
1968 -			    rs->rs_rates[rix] & IEEE80211_RATE_VAL,
1969 +			    "%s: AMRR decreasing rate %d (txcnt=%d retrycnt=%d)",
1970 +			    __func__, rs->rs_rates[rix] & IEEE80211_RATE_VAL,
1971  			    amn->amn_txcnt, amn->amn_retrycnt);
1972  		}
1973  		amn->amn_recovery = 0;
1974 @@ -304,13 +283,7 @@
1975  	const struct ieee80211_rateset *rs = NULL;
1976  	int rix;
1977  
1978 -	/* 11n or not? Pick the right rateset */
1979 -	if (amrr_node_is_11n(ni)) {
1980 -		/* XXX ew */
1981 -		rs = (struct ieee80211_rateset *) &ni->ni_htrates;
1982 -	} else {
1983 -		rs = &ni->ni_rates;
1984 -	}
1985 +	rs = ieee80211_ratectl_get_rateset(ni);
1986  
1987  	if (is_enough(amn) && (ticks - amn->amn_ticks) > amrr->amrr_interval) {
1988  		rix = amrr_update(amrr, amn, ni);
1989 @@ -318,7 +291,7 @@
1990  			/* update public rate */
1991  			ni->ni_txrate = rs->rs_rates[rix];
1992  			/* XXX strip basic rate flag from txrate, if non-11n */
1993 -			if (amrr_node_is_11n(ni))
1994 +			if (ieee80211_ratectl_node_is11n(ni))
1995  				ni->ni_txrate |= IEEE80211_RATE_MCS;
1996  			else
1997  				ni->ni_txrate &= IEEE80211_RATE_VAL;
1998 @@ -330,6 +303,76 @@
1999  	return rix;
2000  }
2001  
2002 +static void
2003 +amrr_rates(struct ieee80211_node *ni, struct ieee80211_rc_info *rc_info)
2004 +{
2005 +#define	RATE(_ix)	(rs->rs_rates[(_ix)] & IEEE80211_RATE_VAL)
2006 +#define	MCS(_ix)	(rs->rs_rates[(_ix)] | IEEE80211_RATE_MCS)
2007 +	struct ieee80211_rc_series *rc = rc_info->iri_rc;
2008 +	const struct ieee80211_rateset *rs = NULL;
2009 +	const struct ieee80211_rate_table *rt = NULL;
2010 +	int rix, code;
2011 +
2012 +	rs = ieee80211_ratectl_get_rateset(ni);
2013 +	rt = ieee80211_get_ratetable(ni->ni_ic->ic_curchan);
2014 +	IEEE80211_DPRINTF(ni->ni_vap, IEEE80211_MSG_RATECTL, 
2015 +	    "%s: channel flags: 0x%08x\n", __func__, 
2016 +		ni->ni_ic->ic_curchan->ic_flags); 
2017 +	
2018 +	rix = amrr_rate(ni, NULL, 0);
2019 +
2020 +	rc[0].flags = rc[1].flags = rc[2].flags = rc[3].flags = 0;
2021 +
2022 +	if (rs->rs_nrates > 0) {
2023 +		code = ieee80211_ratectl_node_is11n(ni)? MCS(rix) : RATE(rix);
2024 +		rc[0].rix = rt->rateCodeToIndex[code];
2025 +
2026 +		if (IEEE80211_RATECTL_HASCAP_MRR(ni->ni_vap)) {
2027 +			rc[0].tries = 1;
2028 +			rc[1].tries = 1;
2029 +			rc[2].tries = 1;
2030 +			rc[3].tries = 1;
2031 +			if (--rix >= 0) {
2032 +				code = ieee80211_ratectl_node_is11n(ni)? MCS(rix) : RATE(rix);
2033 +				rc[1].rix = rt->rateCodeToIndex[code];
2034 +			} else {
2035 +				rc[1].rix = rt->rateCodeToIndex[0];
2036 +			}
2037 +			if (--rix >= 0) {
2038 +				code = ieee80211_ratectl_node_is11n(ni)? MCS(rix) : RATE(rix);
2039 +				rc[2].rix = rt->rateCodeToIndex[code];
2040 +			} else {
2041 +				rc[2].rix = rt->rateCodeToIndex[0];
2042 +			}
2043 +			if (rix >= 0) {
2044 +				/* NB: only do this if we didn't already do it above */
2045 +				code = ieee80211_ratectl_node_is11n(ni)? MCS(0) : RATE(0);
2046 +				rc[3].rix = rt->rateCodeToIndex[code];
2047 +			} else {
2048 +				rc[3].rix = rt->rateCodeToIndex[0];
2049 +			}
2050 +		} else {
2051 +			rc[0].tries = IEEE80211_RATECTL_TXMAXTRY;
2052 +
2053 +			rc[1].tries = 0;
2054 +			rc[2].tries = 0;
2055 +			rc[3].tries = 0;
2056 +			rc[1].rix = rt->rateCodeToIndex[0];
2057 +			rc[2].rix = rt->rateCodeToIndex[0];
2058 +			rc[3].rix = rt->rateCodeToIndex[0];
2059 +		}
2060 +	}
2061 +	IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_RATECTL, ni,
2062 +	    "%s: AMRR rate sets(rix, tries). rc[0]:(%d, %d), rc[1]:(%d, %d), " 
2063 +		"rc[2]:(%d, %d), rc[3]:(%d, %d)", __func__, 
2064 +		rc[0].rix, rc[0].tries,
2065 +		rc[1].rix, rc[1].tries, 
2066 +		rc[2].rix, rc[2].tries, 
2067 +		rc[3].rix, rc[3].tries);
2068 +#undef RATE
2069 +#undef MCS
2070 +}
2071 +
2072  /*
2073   * Update statistics with tx complete status.  Ok is non-zero
2074   * if the packet is known to be ACK'd.  Retries has the number
2075 @@ -337,16 +380,22 @@
2076   */
2077  static void
2078  amrr_tx_complete(const struct ieee80211vap *vap,
2079 -    const struct ieee80211_node *ni, int ok,
2080 -    void *arg1, void *arg2 __unused)
2081 +    const struct ieee80211_node *ni, struct ieee80211_rc_info *rc_info)
2082  {
2083  	struct ieee80211_amrr_node *amn = ni->ni_rctls;
2084 -	int retries = *(int *)arg1;
2085  
2086 -	amn->amn_txcnt++;
2087 -	if (ok)
2088 -		amn->amn_success++;
2089 -	amn->amn_retrycnt += retries;
2090 +	/* update per vap statistics */
2091 +	ieee80211_ratectl_update_stat(vap, rc_info);
2092 +
2093 +	amn->amn_txcnt += rc_info->iri_txcnt;
2094 +	amn->amn_success += (rc_info->iri_txcnt - rc_info->iri_failcnt);
2095 +	amn->amn_retrycnt += rc_info->iri_retrycnt;
2096 +
2097 +	IEEE80211_NOTE(vap, IEEE80211_MSG_RATECTL, ni,
2098 +	    "%s: AMRR tx complete. txcnt=%d(%d) success=%d(%d) retrycnt=%d(%d)\n",
2099 +	    __func__, amn->amn_txcnt, rc_info->iri_txcnt,
2100 +		amn->amn_success, (rc_info->iri_txcnt - rc_info->iri_failcnt),
2101 +		amn->amn_retrycnt, rc_info->iri_retrycnt);
2102  }
2103  
2104  /*
2105 @@ -364,8 +413,21 @@
2106  	amn->amn_txcnt = txcnt;
2107  	amn->amn_success = success;
2108  	amn->amn_retrycnt = retrycnt;
2109 +	IEEE80211_NOTE(vap, IEEE80211_MSG_RATECTL, ni,
2110 +	    "%s: AMRR tx update. txcnt=%d success=%d retrycnt=%d\n",
2111 +	    __func__, txcnt, success, retrycnt);
2112  }
2113  
2114 +static void
2115 +amrr_stats(const struct ieee80211vap *vap)
2116 +{
2117 +	struct ieee80211_rc_stat * irs = IEEE80211_RATECTL_STAT(vap);
2118 +	printf("tx count: %d (ok count: %d, fail count: %d)\n"
2119 +			"retry count: %d (short retry: %d, long retry: %d)\n",
2120 +			irs->irs_txcnt, irs->irs_txcnt - irs->irs_failcnt, irs->irs_failcnt,
2121 +			irs->irs_retrycnt, irs->irs_shortretry, irs->irs_longretry);
2122 +}
2123 +
2124  static int
2125  amrr_sysctl_interval(SYSCTL_HANDLER_ARGS)
2126  {
2127 Index: sys/net80211/ieee80211_freebsd.c
2128 ===================================================================
2129 --- sys/net80211/ieee80211_freebsd.c	(revision 254826)
2130 +++ sys/net80211/ieee80211_freebsd.c	(working copy)
2131 @@ -262,7 +262,9 @@
2132  		"driver_caps", CTLFLAG_RW, &vap->iv_caps, 0,
2133  		"driver capabilities");
2134  #ifdef IEEE80211_DEBUG
2135 +	ieee80211_debug |= (IEEE80211_MSG_RATECTL|IEEE80211_MSG_NODE|IEEE80211_MSG_SCAN);
2136  	vap->iv_debug = ieee80211_debug;
2137 +	if_printf(ifp, "%s: iv_debug=0x%08x\n", __func__, vap->iv_debug);
2138  	SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
2139  		"debug", CTLFLAG_RW, &vap->iv_debug, 0,
2140  		"control debugging printfs");
2141 Index: sys/net80211/ieee80211_sample.c
2142 ===================================================================
2143 --- sys/net80211/ieee80211_sample.c	(revision 0)
2144 +++ sys/net80211/ieee80211_sample.c	(revision 257398)
2145 @@ -0,0 +1,1127 @@
2146 +/* $FreeBSD: head/sys/dev/ath/ath_rate/sample/sample.c 248573 2013-02-27 04:33:06Z adrian $*/
2147 +
2148 +/*-
2149 + * Copyright (c) 2005 John Bicket
2150 + * Copyright (c) 2013 Chenchong Qin <ccqin@FreeBSD.org>
2151 + * All rights reserved.
2152 + *
2153 + * Redistribution and use in source and binary forms, with or without
2154 + * modification, are permitted provided that the following conditions
2155 + * are met:
2156 + * 1. Redistributions of source code must retain the above copyright
2157 + *    notice, this list of conditions and the following disclaimer.
2158 + * 2. Redistributions in binary form must reproduce the above copyright
2159 + *    notice, this list of conditions and the following disclaimer in the
2160 + *    documentation and/or other materials provided with the distribution.
2161 + *
2162 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
2163 + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2164 + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2165 + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2166 + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2167 + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2168 + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2169 + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2170 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2171 + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2172 + */
2173 +
2174 +#include <sys/cdefs.h>
2175 +
2176 +#include "opt_wlan.h"
2177 +
2178 +#include <sys/param.h>
2179 +#include <sys/kernel.h>
2180 +#include <sys/module.h>
2181 +#include <sys/socket.h>
2182 +#include <sys/sysctl.h>
2183 +
2184 +#include <net/if.h>
2185 +#include <net/if_media.h>
2186 +#include <net/ethernet.h>
2187 +
2188 +#ifdef INET
2189 +#include <netinet/in.h>
2190 +#include <netinet/if_ether.h>
2191 +#endif
2192 +
2193 +#include <net80211/ieee80211_var.h>
2194 +#include <net80211/ieee80211_ht.h>
2195 +#include <net80211/ieee80211_ratectl.h>
2196 +#include <net80211/ieee80211_sample.h>
2197 +#include <net80211/ieee80211_sample_txsched.h>
2198 +
2199 +static void	sample_init(struct ieee80211vap *, uint32_t);
2200 +static void	sample_deinit(struct ieee80211vap *);
2201 +static void	sample_node_init(struct ieee80211_node *);
2202 +static void	sample_node_deinit(struct ieee80211_node *);
2203 +static int	sample_rate(struct ieee80211_node *, void *, uint32_t);
2204 +static void	sample_rates(struct ieee80211_node *, struct ieee80211_rc_info *);
2205 +static void	sample_tx_complete(const struct ieee80211vap *,
2206 +    			const struct ieee80211_node *, struct ieee80211_rc_info *);
2207 +static void	sample_tx_update(const struct ieee80211vap *vap,
2208 +			const struct ieee80211_node *, void *, void *, void *);
2209 +static void	sample_stats(const struct ieee80211vap *);
2210 +static void	sample_setinterval(const struct ieee80211vap *, int);
2211 +
2212 +static void	sample_sysctlattach(struct ieee80211vap *,
2213 +			struct sysctl_ctx_list *, struct sysctl_oid *);
2214 +static void	sample_update_static_rix(struct ieee80211_node *);
2215 +
2216 +/* number of references from net80211 layer */
2217 +static	int nrefs = 0;
2218 +
2219 +static const struct ieee80211_ratectl sample = {
2220 +	.ir_name	= "sample",
2221 +	.ir_attach	= NULL,
2222 +	.ir_detach	= NULL,
2223 +	.ir_init	= sample_init,
2224 +	.ir_deinit	= sample_deinit,
2225 +	.ir_node_init	= sample_node_init,
2226 +	.ir_node_deinit	= sample_node_deinit,
2227 +	.ir_rate	= sample_rate,
2228 +	.ir_rates	= sample_rates,
2229 +	.ir_tx_complete	= sample_tx_complete,
2230 +	.ir_tx_update	= sample_tx_update,
2231 +	.ir_setinterval	= sample_setinterval,
2232 +	.ir_stats	= sample_stats,
2233 +};
2234 +IEEE80211_RATECTL_MODULE(sample, 1);
2235 +IEEE80211_RATECTL_ALG(sample, IEEE80211_RATECTL_SAMPLE, sample);
2236 +
2237 +static void
2238 +sample_init(struct ieee80211vap *vap, uint32_t capabilities)
2239 +{
2240 +	struct ieee80211_sample *sample;
2241 +
2242 +	KASSERT(vap->iv_rs == NULL, ("%s called multiple times", __func__));
2243 +
2244 +	sample = vap->iv_rs = malloc(sizeof(struct ieee80211_sample),
2245 +	    M_80211_RATECTL, M_NOWAIT|M_ZERO);
2246 +	if (sample == NULL) {
2247 +		if_printf(vap->iv_ifp, "couldn't alloc ratectl structure\n");
2248 +		return;
2249 +	}
2250 +
2251 +	struct ieee80211_rc_stat * irs = IEEE80211_RATECTL_STAT(vap);
2252 +	irs->irs_capabilities = capabilities;
2253 +
2254 +	sample->sample_smoothing_rate = 75;		/* ewma percentage ([0..99]) */
2255 +	sample->sample_smoothing_minpackets = 100 / (100 - sample->sample_smoothing_rate);
2256 +	sample->sample_rate = 10;			/* %time to try diff tx rates */
2257 +	sample->sample_max_successive_failures = 3;	/* threshold for rate sampling*/
2258 +	sample->sample_stale_failure_timeout = 10 * hz;	/* 10 seconds */
2259 +	sample->sample_min_switch = hz;			/* 1 second */
2260 +	sample_setinterval(vap, 500 /* ms */); 	/* actually do nothing */
2261 +	sample_sysctlattach(vap, vap->iv_sysctl, vap->iv_oid);
2262 +}
2263 +
2264 +static void
2265 +sample_deinit(struct ieee80211vap *vap)
2266 +{
2267 +	free(vap->iv_rs, M_80211_RATECTL);
2268 +}
2269 +
2270 +static const struct txschedule *mrr_schedules[IEEE80211_MODE_MAX+2] = {
2271 +	NULL,		/* IEEE80211_MODE_AUTO */
2272 +	series_11a,	/* IEEE80211_MODE_11A */
2273 +	series_11g,	/* IEEE80211_MODE_11B */
2274 +	series_11g,	/* IEEE80211_MODE_11G */
2275 +	NULL,		/* IEEE80211_MODE_FH */
2276 +	series_11a,	/* IEEE80211_MODE_TURBO_A */
2277 +	series_11g,	/* IEEE80211_MODE_TURBO_G */
2278 +	series_11a,	/* IEEE80211_MODE_STURBO_A */
2279 +	series_11na,	/* IEEE80211_MODE_11NA */
2280 +	series_11ng,	/* IEEE80211_MODE_11NG */
2281 +	series_half,	/* IEEE80211_MODE_HALF */
2282 +	series_quarter,	/* IEEE80211_MODE_QUARTER */
2283 +};
2284 +
2285 +static void
2286 +sample_node_init(struct ieee80211_node *ni)
2287 +{
2288 +#define	RATE(_ix)	(ni->ni_rates.rs_rates[(_ix)] & IEEE80211_RATE_VAL)
2289 +#define	DOT11RATE(_ix)	(rt->info[(_ix)].dot11Rate & IEEE80211_RATE_VAL)
2290 +#define	MCS(_ix)	(ni->ni_htrates.rs_rates[_ix] | IEEE80211_RATE_MCS)
2291 +	
2292 +	struct ieee80211vap *vap = ni->ni_vap;
2293 +	struct ieee80211_sample *sample = vap->iv_rs;
2294 +	struct ieee80211_sample_node *san = NULL;
2295 +
2296 +	const struct ieee80211_rate_table *rt = NULL;
2297 +	enum ieee80211_phymode curmode = ieee80211_chan2mode(vap->iv_ic->ic_curchan);
2298 +	int x, y, rix;
2299 +
2300 +	if (ni->ni_rctls == NULL) {
2301 +		ni->ni_rctls = san = malloc(sizeof(struct ieee80211_sample_node),
2302 +		    M_80211_RATECTL, M_NOWAIT|M_ZERO);
2303 +		if (san == NULL) {
2304 +			if_printf(vap->iv_ifp, "couldn't alloc per-node ratectl "
2305 +			    "structure\n");
2306 +			return;
2307 +		}
2308 +	} else
2309 +		san = ni->ni_rctls;
2310 +	
2311 +	san->san_sample = sample;
2312 +
2313 +	rt = ieee80211_get_ratetable(vap->iv_ic->ic_curchan);
2314 +	KASSERT(rt != NULL, ("no rate table, mode %u", curmode));
2315 +
2316 +	san->sched = mrr_schedules[curmode];
2317 +	KASSERT(san->sched != NULL, ("no mrr schedule for mode %u", curmode));
2318 +
2319 +	san->static_rix = -1;
2320 +	sample_update_static_rix(ni);
2321 +
2322 +	/*
2323 +	 * Construct a bitmask of usable rates.  This has all
2324 +	 * negotiated rates minus those marked by the hal as
2325 +	 * to be ignored for doing rate control.
2326 +	 */
2327 +	san->ratemask = 0;
2328 +
2329 +	/* MCS rates */
2330 +	if (ni->ni_flags & IEEE80211_NODE_HT) {
2331 +		for (x = 0; x < ni->ni_htrates.rs_nrates; x++) {
2332 +			rix = rt->rateCodeToIndex[MCS(x)];
2333 +			if (rix == 0xff)
2334 +				continue;
2335 +			KASSERT(rix < SAMPLE_MAXRATES,
2336 +			    ("mcs %u has rix %d", MCS(x), rix));
2337 +			san->ratemask |= (uint64_t) 1<<rix;
2338 +		}
2339 +	}
2340 +
2341 +	/* Legacy rates */
2342 +	for (x = 0; x < ni->ni_rates.rs_nrates; x++) {
2343 +		rix = rt->rateCodeToIndex[RATE(x)];
2344 +		if (rix == 0xff)
2345 +			continue;
2346 +		KASSERT(rix < SAMPLE_MAXRATES,
2347 +		    ("rate %u has rix %d", RATE(x), rix));
2348 +		san->ratemask |= (uint64_t) 1<<rix;
2349 +	}
2350 +
2351 +	for (y = 0; y < NUM_PACKET_SIZE_BINS; y++) {
2352 +		int size = bin_to_size(y);
2353 +		uint64_t mask;
2354 +
2355 +		san->packets_sent[y] = 0;
2356 +		san->current_sample_rix[y] = -1;
2357 +		san->last_sample_rix[y] = 0;
2358 +		/* XXX start with first valid rate */
2359 +		san->current_rix[y] = ffs(san->ratemask)-1;
2360 +		
2361 +		/*
2362 +		 * Initialize the statistics buckets; these are
2363 +		 * indexed by the rate code index.
2364 +		 */
2365 +		for (rix = 0, mask = san->ratemask; mask != 0; rix++, mask >>= 1) {
2366 +			if ((mask & 1) == 0)		/* not a valid rate */
2367 +				continue;
2368 +			san->stats[y][rix].successive_failures = 0;
2369 +			san->stats[y][rix].tries = 0;
2370 +			san->stats[y][rix].total_packets = 0;
2371 +			san->stats[y][rix].packets_acked = 0;
2372 +			san->stats[y][rix].last_tx = 0;
2373 +			san->stats[y][rix].ewma_pct = 0;
2374 +			
2375 +			san->stats[y][rix].perfect_tx_time =
2376 +			    calc_usecs_unicast_packet(vap, size, rix, 0, 0,
2377 +			    (ni->ni_chw == 40));
2378 +			san->stats[y][rix].average_tx_time =
2379 +			    san->stats[y][rix].perfect_tx_time;
2380 +		}
2381 +	}
2382 +
2383 +	/* set the visible bit-rate */
2384 +	if (san->static_rix != -1)
2385 +		ni->ni_txrate = DOT11RATE(san->static_rix);
2386 +	else
2387 +		ni->ni_txrate = RATE(0);
2388 +#undef RATE
2389 +#undef DOT11RATE
2390 +#undef MCS
2391 +}
2392 +
2393 +static void
2394 +sample_node_deinit(struct ieee80211_node *ni)
2395 +{
2396 +	free(ni->ni_rctls, M_80211_RATECTL);
2397 +}
2398 +
2399 +static int
2400 +dot11rate(const struct ieee80211_rate_table *rt, int rix)
2401 +{
2402 +	if (rix < 0)
2403 +		return -1;
2404 +	return rt->info[rix].phy == IEEE80211_T_HT ?
2405 +	    rt->info[rix].dot11Rate : (rt->info[rix].dot11Rate & IEEE80211_RATE_VAL) / 2;
2406 +}
2407 +
2408 +static const char *
2409 +dot11rate_label(const struct ieee80211_rate_table *rt, int rix)
2410 +{
2411 +	if (rix < 0)
2412 +		return "";
2413 +	return rt->info[rix].phy == IEEE80211_T_HT ? "MCS" : "Mb ";
2414 +}
2415 +
2416 +/*
2417 + * Return the rix with the lowest average_tx_time,
2418 + * or -1 if all the average_tx_times are 0.
2419 + */
2420 +static __inline int
2421 +pick_best_rate(const struct ieee80211_node *ni, const struct ieee80211_rate_table *rt,
2422 +    int size_bin, int require_acked_before)
2423 +{
2424 +	struct ieee80211_sample_node *san = ni->ni_rctls;
2425 +    int best_rate_rix, best_rate_tt, best_rate_pct;
2426 +	uint64_t mask;
2427 +	int rix, tt, pct;
2428 +
2429 +    best_rate_rix = 0;
2430 +    best_rate_tt = 0;
2431 +	best_rate_pct = 0;
2432 +
2433 +	for (mask = san->ratemask, rix = 0; mask != 0; mask >>= 1, rix++) {
2434 +		if ((mask & 1) == 0)		/* not a supported rate */
2435 +			continue;
2436 +
2437 +		/* Don't pick a non-HT rate for a HT node */
2438 +		if ((ni->ni_flags & IEEE80211_NODE_HT) &&
2439 +		    (rt->info[rix].phy != IEEE80211_T_HT)) {
2440 +			continue;
2441 +		}
2442 +
2443 +		tt = san->stats[size_bin][rix].average_tx_time;
2444 +		if (tt <= 0 ||
2445 +		    (require_acked_before &&
2446 +		     !san->stats[size_bin][rix].packets_acked))
2447 +			continue;
2448 +
2449 +		/* Calculate percentage if possible */
2450 +		if (san->stats[size_bin][rix].total_packets > 0) {
2451 +			pct = san->stats[size_bin][rix].ewma_pct;
2452 +		} else {
2453 +			/* XXX for now, assume 95% ok */
2454 +			pct = 95;
2455 +		}
2456 +
2457 +		/* don't use a bit-rate that has been failing */
2458 +		if (san->stats[size_bin][rix].successive_failures > 3)
2459 +			continue;
2460 +
2461 +		/*
2462 +		 * For HT, Don't use a bit rate that is much more
2463 +		 * lossy than the best.
2464 +		 *
2465 +		 * XXX this isn't optimal; it's just designed to
2466 +		 * eliminate rates that are going to be obviously
2467 +		 * worse.
2468 +		 */
2469 +		if (ni->ni_flags & IEEE80211_NODE_HT) {
2470 +			if (best_rate_pct > (pct + 50))
2471 +				continue;
2472 +		}
2473 +
2474 +		/*
2475 +		 * For non-MCS rates, use the current average txtime for
2476 +		 * comparison.
2477 +		 */
2478 +		if (! (ni->ni_flags & IEEE80211_NODE_HT)) {
2479 +			if (best_rate_tt == 0 || tt <= best_rate_tt) {
2480 +				best_rate_tt = tt;
2481 +				best_rate_rix = rix;
2482 +				best_rate_pct = pct;
2483 +			}
2484 +		}
2485 +
2486 +		/*
2487 +		 * Since 2 stream rates have slightly higher TX times,
2488 +		 * allow a little bit of leeway. This should later
2489 +		 * be abstracted out and properly handled.
2490 +		 */
2491 +		if (ni->ni_flags & IEEE80211_NODE_HT) {
2492 +			if (best_rate_tt == 0 || (tt * 8 <= best_rate_tt * 10)) {
2493 +				best_rate_tt = tt;
2494 +				best_rate_rix = rix;
2495 +				best_rate_pct = pct;
2496 +			}
2497 +		}
2498 +        }
2499 +        return (best_rate_tt ? best_rate_rix : -1);
2500 +}
2501 +
2502 +/*
2503 + * Pick a good "random" bit-rate to sample other than the current one.
2504 + */
2505 +static __inline int
2506 +pick_sample_rate(const struct ieee80211_node *ni, 
2507 +		const struct ieee80211_rate_table *rt, int size_bin)
2508 +{
2509 +#define	DOT11RATE(ix)	(rt->info[ix].dot11Rate & IEEE80211_RATE_VAL)
2510 +#define	MCS(ix)		(rt->info[ix].dot11Rate | IEEE80211_RATE_MCS)
2511 +	struct ieee80211_sample_node *san = ni->ni_rctls;
2512 +	struct ieee80211_sample *sample = san->san_sample;
2513 +	int current_rix, rix;
2514 +	unsigned current_tt;
2515 +	uint64_t mask;
2516 +	
2517 +	current_rix = san->current_rix[size_bin];
2518 +	if (current_rix < 0) {
2519 +		/* no successes yet, send at the lowest bit-rate */
2520 +		/* XXX should return MCS0 if HT */
2521 +		return 0;
2522 +	}
2523 +
2524 +	current_tt = san->stats[size_bin][current_rix].average_tx_time;
2525 +
2526 +	rix = san->last_sample_rix[size_bin]+1;	/* next sample rate */
2527 +	mask = san->ratemask &~ ((uint64_t) 1<<current_rix);/* don't sample current rate */
2528 +	while (mask != 0) {
2529 +		if ((mask & ((uint64_t) 1<<rix)) == 0) {	/* not a supported rate */
2530 +	nextrate:
2531 +			if (++rix >= rt->rateCount)
2532 +				rix = 0;
2533 +			continue;
2534 +		}
2535 +
2536 +		/*
2537 +		 * The following code stops trying to sample
2538 +		 * non-MCS rates when speaking to an MCS node.
2539 +		 * However, at least for CCK rates in 2.4GHz mode,
2540 +		 * the non-MCS rates MAY actually provide better
2541 +		 * PER at the very far edge of reception.
2542 +		 *
2543 +		 * However! Until ath_rate_form_aggr() grows
2544 +		 * some logic to not form aggregates if the
2545 +		 * selected rate is non-MCS, this won't work.
2546 +		 *
2547 +		 * So don't disable this code until you've taught
2548 +		 * ath_rate_form_aggr() to drop out if any of
2549 +		 * the selected rates are non-MCS.
2550 +		 */
2551 +#if 1
2552 +		/* if the node is HT and the rate isn't HT, don't bother sample */
2553 +		if ((ni->ni_flags & IEEE80211_NODE_HT) &&
2554 +		    (rt->info[rix].phy != IEEE80211_T_HT)) {
2555 +			mask &= ~((uint64_t) 1<<rix);
2556 +			goto nextrate;
2557 +		}
2558 +#endif
2559 +
2560 +		/* this bit-rate is always worse than the current one */
2561 +		if (san->stats[size_bin][rix].perfect_tx_time > current_tt) {
2562 +			mask &= ~((uint64_t) 1<<rix);
2563 +			goto nextrate;
2564 +		}
2565 +
2566 +		/* rarely sample bit-rates that fail a lot */
2567 +		if (san->stats[size_bin][rix].successive_failures > sample->sample_max_successive_failures &&
2568 +		    ticks - san->stats[size_bin][rix].last_tx < sample->sample_stale_failure_timeout) {
2569 +			mask &= ~((uint64_t) 1<<rix);
2570 +			goto nextrate;
2571 +		}
2572 +
2573 +		/*
2574 +		 * For HT, only sample a few rates on either side of the
2575 +		 * current rix; there's quite likely a lot of them.
2576 +		 */
2577 +		if (ni->ni_flags & IEEE80211_NODE_HT) {
2578 +			if (rix < (current_rix - 3) ||
2579 +			    rix > (current_rix + 3)) {
2580 +				mask &= ~((uint64_t) 1<<rix);
2581 +				goto nextrate;
2582 +			}
2583 +		}
2584 +
2585 +		/* Don't sample more than 2 rates higher for rates > 11M for non-HT rates */
2586 +		if (! (ni->ni_flags & IEEE80211_NODE_HT)) {
2587 +			if (DOT11RATE(rix) > 2*11 && rix > current_rix + 2) {
2588 +				mask &= ~((uint64_t) 1<<rix);
2589 +				goto nextrate;
2590 +			}
2591 +		}
2592 +
2593 +		san->last_sample_rix[size_bin] = rix;
2594 +		return rix;
2595 +	}
2596 +	return current_rix;
2597 +#undef DOT11RATE
2598 +#undef MCS
2599 +}
2600 +
2601 +static int
2602 +sample_get_static_rix(const struct ieee80211_node *ni)
2603 +{
2604 +#define	RATE(_ix)	(ni->ni_rates.rs_rates[(_ix)] & IEEE80211_RATE_VAL)
2605 +#define	MCS(_ix)	(ni->ni_htrates.rs_rates[_ix] | IEEE80211_RATE_MCS)
2606 +	struct ieee80211vap *vap = ni->ni_vap;
2607 +	const struct ieee80211_rate_table *rt = ieee80211_get_ratetable(vap->iv_ic->ic_curchan);
2608 +	const struct ieee80211_txparam *tp = ni->ni_txparms;
2609 +	int srate;
2610 +
2611 +	/* Check MCS rates */
2612 +	for (srate = ni->ni_htrates.rs_nrates - 1; srate >= 0; srate--) {
2613 +		if (MCS(srate) == tp->ucastrate)
2614 +			return rt->rateCodeToIndex[tp->ucastrate];
2615 +	}
2616 +
2617 +	/* Check legacy rates */
2618 +	for (srate = ni->ni_rates.rs_nrates - 1; srate >= 0; srate--) {
2619 +		if (RATE(srate) == tp->ucastrate)
2620 +			return rt->rateCodeToIndex[tp->ucastrate];
2621 +	}
2622 +	return -1;
2623 +#undef	RATE
2624 +#undef	MCS
2625 +}
2626 +
2627 +static void
2628 +sample_update_static_rix(struct ieee80211_node *ni)
2629 +{
2630 +	struct ieee80211_sample_node *san = ni->ni_rctls;
2631 +	const struct ieee80211_txparam *tp = ni->ni_txparms;
2632 +
2633 +	if (tp != NULL && tp->ucastrate != IEEE80211_FIXED_RATE_NONE) {
2634 +		/*
2635 +		 * A fixed rate is to be used; ucastrate is the IEEE code
2636 +		 * for this rate (sans basic bit).  Check this against the
2637 +		 * negotiated rate set for the node.  Note the fixed rate
2638 +		 * may not be available for various reasons so we only
2639 +		 * setup the static rate index if the lookup is successful.
2640 +		 */
2641 +		san->static_rix = sample_get_static_rix(ni);
2642 +	} else {
2643 +		san->static_rix = -1;
2644 +	}
2645 +}
2646 +
2647 +/*
2648 + * Pick a non-HT rate to begin using.
2649 + */
2650 +static int
2651 +sample_pick_seed_rate_legacy(const struct ieee80211_node *ni, int frameLen)
2652 +{
2653 +#define	DOT11RATE(ix)	(rt->info[ix].dot11Rate & IEEE80211_RATE_VAL)
2654 +	struct ieee80211vap *vap = ni->ni_vap;
2655 +	struct ieee80211_sample_node *san = ni->ni_rctls;
2656 +	const struct ieee80211_rate_table *rt = ieee80211_get_ratetable(vap->iv_ic->ic_curchan);
2657 +	
2658 +	const int size_bin = size_to_bin(frameLen);
2659 +	int rix = -1;
2660 +
2661 +	/* no packet has been sent successfully yet */
2662 +	for (rix = rt->rateCount-1; rix > 0; rix--) {
2663 +		if ((san->ratemask & ((uint64_t) 1<<rix)) == 0)
2664 +			continue;
2665 +
2666 +		/* Skip HT rates */
2667 +		if (rt->info[rix].phy == IEEE80211_T_HT)
2668 +			continue;
2669 +
2670 +		/*
2671 +		 * Pick the highest rate <= 36 Mbps
2672 +		 * that hasn't failed.
2673 +		 */
2674 +		if (DOT11RATE(rix) <= 72 &&
2675 +		    san->stats[size_bin][rix].successive_failures == 0) {
2676 +			break;
2677 +		}
2678 +	}
2679 +	return rix;
2680 +#undef DOT11RATE
2681 +}
2682 +
2683 +/*
2684 + * Pick a HT rate to begin using.
2685 + *
2686 + * Don't use any non-HT rates; only consider HT rates.
2687 + */
2688 +static int
2689 +sample_pick_seed_rate_ht(const struct ieee80211_node *ni, int frameLen)
2690 +{
2691 +#define	MCS(ix)		(rt->info[ix].dot11Rate | IEEE80211_RATE_MCS)
2692 +	struct ieee80211vap *vap = ni->ni_vap;
2693 +	struct ieee80211_sample_node *san = ni->ni_rctls;
2694 +	const struct ieee80211_rate_table *rt = ieee80211_get_ratetable(vap->iv_ic->ic_curchan);
2695 +	
2696 +	const int size_bin = size_to_bin(frameLen);
2697 +	int rix = -1, ht_rix = -1;
2698 +
2699 +	/* no packet has been sent successfully yet */
2700 +	for (rix = rt->rateCount-1; rix > 0; rix--) {
2701 +		/* Skip rates we can't use */
2702 +		if ((san->ratemask & ((uint64_t) 1<<rix)) == 0)
2703 +			continue;
2704 +
2705 +		/* Keep a copy of the last seen HT rate index */
2706 +		if (rt->info[rix].phy == IEEE80211_T_HT)
2707 +			ht_rix = rix;
2708 +
2709 +		/* Skip non-HT rates */
2710 +		if (rt->info[rix].phy != IEEE80211_T_HT)
2711 +			continue;
2712 +
2713 +		/*
2714 +		 * Pick a medium-speed rate regardless of stream count
2715 +		 * which has not seen any failures. Higher rates may fail;
2716 +		 * we'll try them later.
2717 +		 */
2718 +		if (((MCS(rix) & 0x7) <= 4) &&
2719 +		    san->stats[size_bin][rix].successive_failures == 0) {
2720 +			break;
2721 +		}
2722 +	}
2723 +
2724 +	/*
2725 +	 * If all the MCS rates have successive failures, rix should be
2726 +	 * > 0; otherwise use the lowest MCS rix (hopefully MCS 0.)
2727 +	 */
2728 +	return MAX(rix, ht_rix);
2729 +#undef MCS
2730 +}
2731 +
2732 +static int
2733 +sample_rate(struct ieee80211_node *ni, void *arg __unused, uint32_t iarg __unused)
2734 +{
2735 +#define	DOT11RATE(ix)	(rt->info[ix].dot11Rate & IEEE80211_RATE_VAL)
2736 +#define	MCS(ix)		(rt->info[ix].dot11Rate | IEEE80211_RATE_MCS)
2737 +#define	RATE(ix)	(DOT11RATE(ix) / 2)
2738 +	struct ieee80211vap *vap = ni->ni_vap;
2739 +	struct ieee80211_sample_node *san = ni->ni_rctls;
2740 +	struct ieee80211_sample *sample = san->san_sample;
2741 +	const struct ieee80211_rate_table *rt = ieee80211_get_ratetable(vap->iv_ic->ic_curchan);
2742 +	
2743 +	int rix, mrr, best_rix, change_rates;
2744 +	unsigned average_tx_time;
2745 +	
2746 +	size_t frameLen = (size_t)iarg;
2747 +	const int size_bin = size_to_bin(frameLen);
2748 +
2749 +	sample_update_static_rix(ni);
2750 +
2751 +	if (san->static_rix != -1) {
2752 +		rix = san->static_rix;
2753 +		goto done;
2754 +	}
2755 +
2756 +	if (IEEE80211_RATECTL_HASCAP_MRR(vap))
2757 +		mrr = 1;
2758 +	if (! IEEE80211_RATECTL_HASCAP_MRRPROT(vap))
2759 +		mrr = 0;
2760 +
2761 +	best_rix = pick_best_rate(ni, rt, size_bin, !mrr);
2762 +	if (best_rix >= 0) {
2763 +		average_tx_time = san->stats[size_bin][best_rix].average_tx_time;
2764 +	} else {
2765 +		average_tx_time = 0;
2766 +	}
2767 +
2768 +	/*
2769 +	 * Limit the time measuring the performance of other tx
2770 +	 * rates to sample_rate% of the total transmission time.
2771 +	 */
2772 +	if (san->sample_tt[size_bin] < average_tx_time * (san->packets_since_sample[size_bin] *
2773 +		sample->sample_rate/100)) {
2774 +		rix = pick_sample_rate(ni, rt, size_bin);
2775 +		IEEE80211_NOTE(vap, IEEE80211_MSG_RATECTL,
2776 +		     ni, "att %d sample_tt %d size %u sample rate %d %s current rate %d %s",
2777 +		     average_tx_time,
2778 +		     san->sample_tt[size_bin],
2779 +		     bin_to_size(size_bin),
2780 +		     dot11rate(rt, rix),
2781 +		     dot11rate_label(rt, rix),
2782 +		     dot11rate(rt, san->current_rix[size_bin]),
2783 +		     dot11rate_label(rt, san->current_rix[size_bin]));
2784 +		if (rix != san->current_rix[size_bin]) {
2785 +			san->current_sample_rix[size_bin] = rix;
2786 +		} else {
2787 +			san->current_sample_rix[size_bin] = -1;
2788 +		}
2789 +		san->packets_since_sample[size_bin] = 0;
2790 +	} else {
2791 +		change_rates = 0;
2792 +		if (!san->packets_sent[size_bin] || best_rix == -1) {
2793 +			/* no packet has been sent successfully yet */
2794 +			change_rates = 1;
2795 +			if (ni->ni_flags & IEEE80211_NODE_HT)
2796 +				best_rix = sample_pick_seed_rate_ht(ni, frameLen);
2797 +			else
2798 +				best_rix = sample_pick_seed_rate_legacy(ni, frameLen);
2799 +		} else if (san->packets_sent[size_bin] < 20) {
2800 +			/* let the bit-rate switch quickly during the first few packets */
2801 +			IEEE80211_NOTE(vap,
2802 +			    IEEE80211_MSG_RATECTL, ni,
2803 +			    "%s: switching quickly..", __func__);
2804 +			change_rates = 1;
2805 +		} else if (ticks - sample->sample_min_switch > san->ticks_since_switch[size_bin]) {
2806 +			/* min_switch seconds have gone by */
2807 +			IEEE80211_NOTE(vap,
2808 +			    IEEE80211_MSG_RATECTL, ni,
2809 +			    "%s: min_switch %d > ticks_since_switch %d..",
2810 +			    __func__, ticks - sample->sample_min_switch, san->ticks_since_switch[size_bin]);
2811 +			change_rates = 1;
2812 +		} else if ((! (ni->ni_flags & IEEE80211_NODE_HT)) &&
2813 +		    (2*average_tx_time < san->stats[size_bin][san->current_rix[size_bin]].average_tx_time)) {
2814 +			/* the current bit-rate is twice as slow as the best one */
2815 +			IEEE80211_NOTE(vap,
2816 +			    IEEE80211_MSG_RATECTL, ni,
2817 +			    "%s: 2x att (= %d) < cur_rix att %d",
2818 +			    __func__,
2819 +			    2 * average_tx_time, san->stats[size_bin][san->current_rix[size_bin]].average_tx_time);
2820 +			change_rates = 1;
2821 +		} else if ((ni->ni_flags & IEEE80211_NODE_HT)) {
2822 +			int cur_rix = san->current_rix[size_bin];
2823 +			int cur_att = san->stats[size_bin][cur_rix].average_tx_time;
2824 +			/*
2825 +			 * If the node is HT, upgrade it if the MCS rate is
2826 +			 * higher and the average tx time is within 20% of
2827 +			 * the current rate. It can fail a little.
2828 +			 *
2829 +			 * This is likely not optimal!
2830 +			 */
2831 +#if 0
2832 +			printf("cur rix/att %x/%d, best rix/att %x/%d\n",
2833 +			    MCS(cur_rix), cur_att, MCS(best_rix), average_tx_time);
2834 +#endif
2835 +			if ((MCS(best_rix) > MCS(cur_rix)) &&
2836 +			    (average_tx_time * 8) <= (cur_att * 10)) {
2837 +				IEEE80211_NOTE(vap,
2838 +				    IEEE80211_MSG_RATECTL, ni,
2839 +				    "%s: HT: best_rix 0x%d > cur_rix 0x%x, average_tx_time %d, cur_att %d",
2840 +				    __func__,
2841 +				    MCS(best_rix), MCS(cur_rix), average_tx_time, cur_att);
2842 +				change_rates = 1;
2843 +			}
2844 +		}
2845 +
2846 +		san->packets_since_sample[size_bin]++;
2847 +		
2848 +		if (change_rates) {
2849 +			if (best_rix != san->current_rix[size_bin]) {
2850 +				IEEE80211_NOTE(vap,
2851 +				    IEEE80211_MSG_RATECTL,
2852 +				    ni,
2853 +"%s: size %d switch rate %d (%d/%d) -> %d (%d/%d) after %d packets mrr %d",
2854 +				    __func__,
2855 +				    bin_to_size(size_bin),
2856 +				    RATE(san->current_rix[size_bin]),
2857 +				    san->stats[size_bin][san->current_rix[size_bin]].average_tx_time,
2858 +				    san->stats[size_bin][san->current_rix[size_bin]].perfect_tx_time,
2859 +				    RATE(best_rix),
2860 +				    san->stats[size_bin][best_rix].average_tx_time,
2861 +				    san->stats[size_bin][best_rix].perfect_tx_time,
2862 +				    san->packets_since_switch[size_bin],
2863 +				    mrr);
2864 +			}
2865 +			san->packets_since_switch[size_bin] = 0;
2866 +			san->current_rix[size_bin] = best_rix;
2867 +			san->ticks_since_switch[size_bin] = ticks;
2868 +			/* 
2869 +			 * Set the visible txrate for this node.
2870 +			 */
2871 +			ni->ni_txrate = dot11rate(rt, best_rix);
2872 +		}
2873 +		rix = san->current_rix[size_bin];
2874 +		san->packets_since_switch[size_bin]++;
2875 +	}
2876 +	// *try0 = mrr ? san->sched[rix].t0 : ATH_TXMAXTRY;
2877 +done:
2878 +
2879 +	/*
2880 +	 * This bug totally sucks and should be fixed.
2881 +	 *
2882 +	 * For now though, let's not panic, so we can start to figure
2883 +	 * out how to better reproduce it.
2884 +	 */
2885 +	if (rix < 0 || rix >= rt->rateCount) {
2886 +		printf("%s: ERROR: rix %d out of bounds (rateCount=%d)\n",
2887 +		    __func__,
2888 +		    rix,
2889 +		    rt->rateCount);
2890 +		    rix = 0;	/* XXX just default for now */
2891 +	}
2892 +	KASSERT(rix >= 0 && rix < rt->rateCount, ("rix is %d", rix));
2893 +
2894 +	// *rix0 = rix;
2895 +	// *txrate = rt->info[rix].rateCode
2896 +	// 	| (shortPreamble ? rt->info[rix].shortPreamble : 0);
2897 +	san->packets_sent[size_bin]++;
2898 +
2899 +	return rix;
2900 +#undef DOT11RATE
2901 +#undef MCS
2902 +#undef RATE
2903 +}
2904 +
2905 +static void
2906 +sample_rates(struct ieee80211_node *ni, struct ieee80211_rc_info *rc_info)
2907 +{
2908 +	struct ieee80211_sample_node *san = ni->ni_rctls;
2909 +	uint8_t rix0 = sample_rate(ni, NULL, 0);
2910 +	const struct txschedule *sched = &san->sched[rix0];
2911 +	struct ieee80211_rc_series *rc = rc_info->iri_rc;
2912 +
2913 +	KASSERT(rix0 == sched->r0, ("rix0 (%x) != sched->r0 (%x)!\n",
2914 +	    rix0, sched->r0));
2915 +	/* XXX */
2916 +	rc[0].flags = rc[1].flags = rc[2].flags = rc[3].flags = 0;
2917 +
2918 +	rc[0].rix = sched->r0;
2919 +	rc[1].rix = sched->r1;
2920 +	rc[2].rix = sched->r2;
2921 +	rc[3].rix = sched->r3;
2922 +
2923 +	rc[0].tries = sched->t0;
2924 +	rc[1].tries = sched->t1;
2925 +	rc[2].tries = sched->t2;
2926 +	rc[3].tries = sched->t3;
2927 +}
2928 +
2929 +static void
2930 +update_stats(const struct ieee80211vap *vap,
2931 +    	  const struct ieee80211_node *ni,
2932 +		  int frame_size,
2933 +		  int rix0, int tries0,
2934 +		  int rix1, int tries1,
2935 +		  int rix2, int tries2,
2936 +		  int rix3, int tries3,
2937 +		  int short_tries, int tries,
2938 +		  int nframes, int nbad)
2939 +{
2940 +	struct ieee80211_sample_node *san = ni->ni_rctls;
2941 +	struct ieee80211_sample *sample = san->san_sample;
2942 +
2943 +	const int size_bin = size_to_bin(frame_size);
2944 +	const int size = bin_to_size(size_bin);
2945 +
2946 +	int is_ht40 = ieee80211_ratectl_hascap_cw40(ni);
2947 +	int tt, tries_so_far;
2948 +	int pct;
2949 +
2950 +	if (!IS_RATE_DEFINED(san, rix0))
2951 +		return;
2952 +	tt = calc_usecs_unicast_packet(vap, size, rix0, short_tries,
2953 +		MIN(tries0, tries) - 1, is_ht40);
2954 +	tries_so_far = tries0;
2955 +
2956 +	if (tries1 && tries_so_far < tries) {
2957 +		if (!IS_RATE_DEFINED(san, rix1))
2958 +			return;
2959 +		tt += calc_usecs_unicast_packet(vap, size, rix1, short_tries,
2960 +			MIN(tries1 + tries_so_far, tries) - tries_so_far - 1, is_ht40);
2961 +		tries_so_far += tries1;
2962 +	}
2963 +
2964 +	if (tries2 && tries_so_far < tries) {
2965 +		if (!IS_RATE_DEFINED(san, rix2))
2966 +			return;
2967 +		tt += calc_usecs_unicast_packet(vap, size, rix2, short_tries,
2968 +			MIN(tries2 + tries_so_far, tries) - tries_so_far - 1, is_ht40);
2969 +		tries_so_far += tries2;
2970 +	}
2971 +
2972 +	if (tries3 && tries_so_far < tries) {
2973 +		if (!IS_RATE_DEFINED(san, rix3))
2974 +			return;
2975 +		tt += calc_usecs_unicast_packet(vap, size, rix3, short_tries,
2976 +			MIN(tries3 + tries_so_far, tries) - tries_so_far - 1, is_ht40);
2977 +	}
2978 +
2979 +	if (san->stats[size_bin][rix0].total_packets < sample->sample_smoothing_minpackets) {
2980 +		/* just average the first few packets */
2981 +		int avg_tx = san->stats[size_bin][rix0].average_tx_time;
2982 +		int packets = san->stats[size_bin][rix0].total_packets;
2983 +		san->stats[size_bin][rix0].average_tx_time = (tt+(avg_tx*packets))/(packets+nframes);
2984 +	} else {
2985 +		/* use a ewma */
2986 +		san->stats[size_bin][rix0].average_tx_time = 
2987 +			((san->stats[size_bin][rix0].average_tx_time * sample->sample_smoothing_rate) + 
2988 +			 (tt * (100 - sample->sample_smoothing_rate))) / 100;
2989 +	}
2990 +	
2991 +	/*
2992 +	 * XXX Don't mark the higher bit rates as also having failed; as this
2993 +	 * unfortunately stops those rates from being tasted when trying to
2994 +	 * TX. This happens with 11n aggregation.
2995 +	 */
2996 +	if (nframes == nbad) {
2997 +		san->stats[size_bin][rix0].successive_failures += nbad;
2998 +
2999 +	} else {
3000 +		san->stats[size_bin][rix0].packets_acked += (nframes - nbad);
3001 +		san->stats[size_bin][rix0].successive_failures = 0;
3002 +	}
3003 +	san->stats[size_bin][rix0].tries += tries;
3004 +	san->stats[size_bin][rix0].last_tx = ticks;
3005 +	san->stats[size_bin][rix0].total_packets += nframes;
3006 +
3007 +	/* update EWMA for this rix */
3008 +
3009 +	/* Calculate percentage based on current rate */
3010 +	if (nframes == 0)
3011 +		nframes = nbad = 1;
3012 +	pct = ((nframes - nbad) * 1000) / nframes;
3013 +
3014 +	if (san->stats[size_bin][rix0].total_packets <
3015 +	    sample->sample_smoothing_minpackets) {
3016 +		/* just average the first few packets */
3017 +		int a_pct = (san->stats[size_bin][rix0].packets_acked * 1000) /
3018 +		    (san->stats[size_bin][rix0].total_packets);
3019 +		san->stats[size_bin][rix0].ewma_pct = a_pct;
3020 +	} else {
3021 +		/* use a ewma */
3022 +		san->stats[size_bin][rix0].ewma_pct =
3023 +			((san->stats[size_bin][rix0].ewma_pct * sample->sample_smoothing_rate) +
3024 +			 (pct * (100 - sample->sample_smoothing_rate))) / 100;
3025 +	}
3026 +
3027 +	if (rix0 == san->current_sample_rix[size_bin]) {
3028 +		san->sample_tt[size_bin] = tt;
3029 +		san->current_sample_rix[size_bin] = -1;
3030 +	}
3031 +}
3032 +
3033 +static void
3034 +sample_tx_complete(const struct ieee80211vap *vap,
3035 +    const struct ieee80211_node *ni, struct ieee80211_rc_info *rc_info)
3036 +{
3037 +	struct ieee80211_sample_node *san = ni->ni_rctls;
3038 +	const struct ieee80211_rate_table *rt = NULL;
3039 +	struct ieee80211_rc_series *rc = NULL;
3040 +	int final_rix, short_tries, long_tries;
3041 +	int nframes, nbad;
3042 +	int frame_size, mrr;
3043 +
3044 +	rt = ieee80211_get_ratetable(vap->iv_ic->ic_curchan);
3045 +	rc = rc_info->iri_rc;	
3046 +	/* update per vap statistics */
3047 +	ieee80211_ratectl_update_stat(vap, rc_info);
3048 +
3049 +	final_rix = rt->rateCodeToIndex[rc_info->iri_txrate];
3050 +	short_tries = rc_info->iri_shortretry;
3051 +	long_tries = rc_info->iri_longretry + 1;
3052 +
3053 +	nframes = rc_info->iri_txcnt;
3054 +	nbad = rc_info->iri_failcnt;
3055 +
3056 +	frame_size = rc_info->iri_framelen;
3057 +	mrr = 0;
3058 +
3059 +	if (nframes == 0) {
3060 +		/* XXX need some msg out */
3061 +		return;
3062 +	}
3063 +
3064 +	if (frame_size == 0)		    /* NB: should not happen */
3065 +		frame_size = 1500;
3066 +
3067 +	if (san->ratemask == 0) {
3068 +		return;
3069 +	}
3070 +	
3071 +	if (IEEE80211_RATECTL_HASCAP_MRR(vap))
3072 +		mrr = 1;
3073 +	/* XXX check HT protmode too */
3074 +	if (mrr && !IEEE80211_RATECTL_HASCAP_MRRPROT(vap))
3075 +		mrr = 0;
3076 +	
3077 +	if (!mrr || rc_info->iri_finaltsi == 0) {
3078 +		if (!IS_RATE_DEFINED(san, final_rix)) {
3079 +			return;
3080 +		}
3081 +		/*
3082 +		 * Only one rate was used; optimize work.
3083 +		 */
3084 +		update_stats(vap, ni, frame_size, 
3085 +			     final_rix, long_tries,
3086 +			     0, 0,
3087 +			     0, 0,
3088 +			     0, 0,
3089 +			     short_tries, long_tries,
3090 +			     nframes, nbad);
3091 +
3092 +	} else {
3093 +		int finalTSIdx = rc_info->iri_finaltsi;
3094 +
3095 +		/*
3096 +		 * NB: series > 0 are not penalized for failure
3097 +		 * based on the try counts under the assumption
3098 +		 * that losses are often bursty and since we
3099 +		 * sample higher rates 1 try at a time doing so
3100 +		 * may unfairly penalize them.
3101 +		 */
3102 +		if (rc[0].tries) {
3103 +			update_stats(vap, ni, frame_size,
3104 +				     rc[0].rix, rc[0].tries,
3105 +				     rc[1].rix, rc[1].tries,
3106 +				     rc[2].rix, rc[2].tries,
3107 +				     rc[3].rix, rc[3].tries,
3108 +				     short_tries, long_tries,
3109 +				     nframes, nbad);
3110 +			long_tries -= rc[0].tries;
3111 +		}
3112 +		
3113 +		if (rc[1].tries && finalTSIdx > 0) {
3114 +			update_stats(vap, ni, frame_size,
3115 +				     rc[1].rix, rc[1].tries,
3116 +				     rc[2].rix, rc[2].tries,
3117 +				     rc[3].rix, rc[3].tries,
3118 +				     0, 0,
3119 +				     short_tries, long_tries,
3120 +				     nframes, nbad);
3121 +			long_tries -= rc[1].tries;
3122 +		}
3123 +
3124 +		if (rc[2].tries && finalTSIdx > 1) {
3125 +			update_stats(vap, ni, frame_size,
3126 +				     rc[2].rix, rc[2].tries,
3127 +				     rc[3].rix, rc[3].tries,
3128 +				     0, 0,
3129 +				     0, 0,
3130 +				     short_tries, long_tries,
3131 +				     nframes, nbad);
3132 +			long_tries -= rc[2].tries;
3133 +		}
3134 +
3135 +		if (rc[3].tries && finalTSIdx > 2) {
3136 +			update_stats(vap, ni, frame_size,
3137 +				     rc[3].rix, rc[3].tries,
3138 +				     0, 0,
3139 +				     0, 0,
3140 +				     0, 0,
3141 +				     short_tries, long_tries,
3142 +				     nframes, nbad);
3143 +		}
3144 +	}
3145 +}
3146 +
3147 +static void
3148 +sample_tx_update(const struct ieee80211vap *vap, const struct ieee80211_node *ni,
3149 +    void *arg1, void *arg2, void *arg3)
3150 +{
3151 +	/* nothing here. */
3152 +}
3153 +
3154 +static void
3155 +sample_setinterval(const struct ieee80211vap *vap, int msecs)
3156 +{
3157 +	/* ieee80211_sample doesn't have the sample_interval field by now */
3158 +}
3159 +
3160 +static void
3161 +sample_stats_node(void *arg, struct ieee80211_node *ni)
3162 +{
3163 +	struct ieee80211vap *vap = ni->ni_vap;
3164 +	struct ieee80211_sample_node *san = ni->ni_rctls;
3165 +	const struct ieee80211_rate_table *rt = ieee80211_get_ratetable(vap->iv_ic->ic_curchan);
3166 +	uint64_t mask;
3167 +	int rix, y;
3168 +
3169 +	printf("\n[%s] refcnt %d static_rix (%d %s) ratemask 0x%jx\n",
3170 +	    ether_sprintf(ni->ni_macaddr), ieee80211_node_refcnt(ni),
3171 +	    dot11rate(rt, san->static_rix),
3172 +	    dot11rate_label(rt, san->static_rix),
3173 +	    (uintmax_t)san->ratemask);
3174 +	for (y = 0; y < NUM_PACKET_SIZE_BINS; y++) {
3175 +		printf("[%4u] cur rix %d (%d %s) since switch: packets %d ticks %u\n",
3176 +		    bin_to_size(y), san->current_rix[y],
3177 +		    dot11rate(rt, san->current_rix[y]),
3178 +		    dot11rate_label(rt, san->current_rix[y]),
3179 +		    san->packets_since_switch[y], san->ticks_since_switch[y]);
3180 +		printf("[%4u] last sample (%d %s) cur sample (%d %s) packets sent %d\n",
3181 +		    bin_to_size(y),
3182 +		    dot11rate(rt, san->last_sample_rix[y]),
3183 +		    dot11rate_label(rt, san->last_sample_rix[y]),
3184 +		    dot11rate(rt, san->current_sample_rix[y]),
3185 +		    dot11rate_label(rt, san->current_sample_rix[y]),
3186 +		    san->packets_sent[y]);
3187 +		printf("[%4u] packets since sample %d sample tt %u\n",
3188 +		    bin_to_size(y), san->packets_since_sample[y],
3189 +		    san->sample_tt[y]);
3190 +	}
3191 +	for (mask = san->ratemask, rix = 0; mask != 0; mask >>= 1, rix++) {
3192 +		if ((mask & 1) == 0)
3193 +				continue;
3194 +		for (y = 0; y < NUM_PACKET_SIZE_BINS; y++) {
3195 +			if (san->stats[y][rix].total_packets == 0)
3196 +				continue;
3197 +			printf("[%2u %s:%4u] %8ju:%-8ju (%3d%%) (EWMA %3d.%1d%%) T %8ju F %4d avg %5u last %u\n",
3198 +			    dot11rate(rt, rix), dot11rate_label(rt, rix),
3199 +			    bin_to_size(y),
3200 +			    (uintmax_t) san->stats[y][rix].total_packets,
3201 +			    (uintmax_t) san->stats[y][rix].packets_acked,
3202 +			    (int) ((san->stats[y][rix].packets_acked * 100ULL) /
3203 +			     san->stats[y][rix].total_packets),
3204 +			    san->stats[y][rix].ewma_pct / 10,
3205 +			    san->stats[y][rix].ewma_pct % 10,
3206 +			    (uintmax_t) san->stats[y][rix].tries,
3207 +			    san->stats[y][rix].successive_failures,
3208 +			    san->stats[y][rix].average_tx_time,
3209 +			    ticks - san->stats[y][rix].last_tx);
3210 +		}
3211 +	}
3212 +}
3213 +static void
3214 +sample_stats(const struct ieee80211vap *vap)
3215 +{
3216 +	struct ieee80211com *ic = vap->iv_ifp->if_l2com;
3217 +	struct ieee80211_rc_stat * irs = IEEE80211_RATECTL_STAT(vap);
3218 +	printf("tx count: %d (ok count: %d, fail count: %d)\n"
3219 +			"retry count: %d (short retry: %d, long retry: %d)\n",
3220 +			irs->irs_txcnt, irs->irs_txcnt - irs->irs_failcnt, irs->irs_failcnt,
3221 +			irs->irs_retrycnt, irs->irs_shortretry, irs->irs_longretry);
3222 +	ieee80211_iterate_nodes(&ic->ic_sta, sample_stats_node, NULL);
3223 +}
3224 +
3225 +static int
3226 +sample_sysctl_smoothing_rate(SYSCTL_HANDLER_ARGS)
3227 +{
3228 +	struct ieee80211vap *vap = arg1;
3229 +	struct ieee80211_sample *sample = vap->iv_rs;
3230 +	int rate, error;
3231 +
3232 +	rate = sample->sample_smoothing_rate;
3233 +	error = sysctl_handle_int(oidp, &rate, 0, req);
3234 +	if (error || !req->newptr)
3235 +		return error;
3236 +	if (!(0 <= rate && rate < 100))
3237 +		return EINVAL;
3238 +	sample->sample_smoothing_rate = rate;
3239 +	sample->sample_smoothing_minpackets = 100 / (100 - rate);
3240 +	return 0;
3241 +}
3242 +
3243 +static int
3244 +sample_sysctl_sample_rate(SYSCTL_HANDLER_ARGS)
3245 +{
3246 +	struct ieee80211vap *vap = arg1;
3247 +	struct ieee80211_sample *sample = vap->iv_rs;
3248 +	int rate, error;
3249 +
3250 +	rate = sample->sample_rate;
3251 +	error = sysctl_handle_int(oidp, &rate, 0, req);
3252 +	if (error || !req->newptr)
3253 +		return error;
3254 +	if (!(2 <= rate && rate <= 100))
3255 +		return EINVAL;
3256 +	sample->sample_rate = rate;
3257 +	return 0;
3258 +}
3259 +
3260 +static void
3261 +sample_sysctlattach(struct ieee80211vap *vap,
3262 +    struct sysctl_ctx_list *ctx, struct sysctl_oid *tree)
3263 +{
3264 +	SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
3265 +	    "sample_smoothing_rate", CTLTYPE_INT | CTLFLAG_RW, vap, 0,
3266 +	    sample_sysctl_smoothing_rate, "I",
3267 +	    "sample: smoothing rate for avg tx time (%%)");
3268 +	SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
3269 +	    "sample_rate", CTLTYPE_INT | CTLFLAG_RW, vap, 0,
3270 +	    sample_sysctl_sample_rate, "I",
3271 +	    "sample: percent air time devoted to sampling new rates (%%)");
3272 +}
3273 Index: sys/net80211/ieee80211_sample.h
3274 ===================================================================
3275 --- sys/net80211/ieee80211_sample.h	(revision 0)
3276 +++ sys/net80211/ieee80211_sample.h	(revision 257398)
3277 @@ -0,0 +1,288 @@
3278 +/* $FreeBSD: head/sys/dev/ath/ath_rate/sample/sample.h 240382 2012-08-15 07:10:10Z adrian $*/
3279 +
3280 +/*-
3281 + * Copyright (c) 2005 John Bicket
3282 + * Copyright (c) 2013 Chenchong Qin <ccqin@FreeBSD.org>
3283 + * All rights reserved.
3284 + *
3285 + * Redistribution and use in source and binary forms, with or without
3286 + * modification, are permitted provided that the following conditions
3287 + * are met:
3288 + * 1. Redistributions of source code must retain the above copyright
3289 + *    notice, this list of conditions and the following disclaimer,
3290 + *    without modification.
3291 + * 2. Redistributions in binary form must reproduce at minimum a disclaimer
3292 + *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
3293 + *    redistribution must be conditioned upon including a substantially
3294 + *    similar Disclaimer requirement for further binary redistribution.
3295 + * 3. Neither the names of the above-listed copyright holders nor the names
3296 + *    of any contributors may be used to endorse or promote products derived
3297 + *    from this software without specific prior written permission.
3298 + *
3299 + * Alternatively, this software may be distributed under the terms of the
3300 + * GNU General Public License ("GPL") version 2 as published by the Free
3301 + * Software Foundation.
3302 + *
3303 + * NO WARRANTY
3304 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
3305 + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3306 + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
3307 + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
3308 + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
3309 + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
3310 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
3311 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
3312 + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
3313 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
3314 + * THE POSSIBILITY OF SUCH DAMAGES.
3315 + */
3316 +
3317 +#ifndef _NET80211_IEEE80211_RATECTL_SAMPLE_H_
3318 +#define _NET80211_IEEE80211_RATECTL_SAMPLE_H_
3319 +
3320 +#include <net80211/ieee80211_ratectl.h>
3321 +
3322 +/*
3323 + * for now, we track performance for three different packet
3324 + * size buckets
3325 + */
3326 +#define NUM_PACKET_SIZE_BINS 2
3327 +#define	SAMPLE_MAXRATES	64		/* NB: corresponds to hal info[32] */
3328 +
3329 +/*
3330 + * Rate control settings.
3331 + */
3332 +struct ieee80211_sample {
3333 +	struct ieee80211_rc_stat sample_stat;
3334 +	int	sample_smoothing_rate;			/* ewma percentage [0..99] */
3335 +	int	sample_smoothing_minpackets;
3336 +	int	sample_rate;			/* %time to try different tx rates */
3337 +	int	sample_max_successive_failures;
3338 +	int	sample_stale_failure_timeout;	/* how long to honor max_successive_failures */
3339 +	int	sample_min_switch;		/* min time between rate changes */
3340 +	int	sample_min_good_pct;	/* min good percentage for a rate to be considered */
3341 +};
3342 +
3343 +struct rate_stats {	
3344 +	unsigned average_tx_time;
3345 +	int successive_failures;
3346 +	uint64_t tries;
3347 +	uint64_t total_packets;	/* pkts total since assoc */
3348 +	uint64_t packets_acked;	/* pkts acked since assoc */
3349 +	int ewma_pct;	/* EWMA percentage */
3350 +	unsigned perfect_tx_time; /* transmit time for 0 retries */
3351 +	int last_tx;
3352 +};
3353 +
3354 +struct txschedule {
3355 +	uint8_t	t0, r0;		/* series 0: tries, rate code */
3356 +	uint8_t	t1, r1;		/* series 1: tries, rate code */
3357 +	uint8_t	t2, r2;		/* series 2: tries, rate code */
3358 +	uint8_t	t3, r3;		/* series 3: tries, rate code */
3359 +};
3360 +
3361 +/*
3362 + * Rate control state for a given node.
3363 + */
3364 +/* XXX change naming conversion? */
3365 +struct ieee80211_sample_node {
3366 +	struct ieee80211_sample *san_sample;/* backpointer */
3367 +	int static_rix;			/* rate index of fixed tx rate */
3368 +	uint64_t ratemask;		/* bit mask of valid rate indices */
3369 +	const struct txschedule *sched;	/* tx schedule table */
3370 +
3371 +	struct rate_stats stats[NUM_PACKET_SIZE_BINS][SAMPLE_MAXRATES];
3372 +	int last_sample_rix[NUM_PACKET_SIZE_BINS];
3373 +
3374 +	int current_sample_rix[NUM_PACKET_SIZE_BINS];       
3375 +	int packets_sent[NUM_PACKET_SIZE_BINS];
3376 +
3377 +	int current_rix[NUM_PACKET_SIZE_BINS];
3378 +	int packets_since_switch[NUM_PACKET_SIZE_BINS];
3379 +	unsigned ticks_since_switch[NUM_PACKET_SIZE_BINS];
3380 +
3381 +	int packets_since_sample[NUM_PACKET_SIZE_BINS];
3382 +	unsigned sample_tt[NUM_PACKET_SIZE_BINS];
3383 +};
3384 +
3385 +#define	IS_RATE_DEFINED(san, rix)	(((san)->ratemask & (1<<(rix))) != 0)
3386 +
3387 +#ifndef MIN
3388 +#define	MIN(a,b)	((a) < (b) ? (a) : (b))
3389 +#endif
3390 +#ifndef MAX
3391 +#define	MAX(a,b)	((a) > (b) ? (a) : (b))
3392 +#endif
3393 +
3394 +static const int packet_size_bins[NUM_PACKET_SIZE_BINS]  = { 250, 1600 };
3395 +
3396 +static inline int
3397 +bin_to_size(int index)
3398 +{
3399 +	return packet_size_bins[index];
3400 +}
3401 +
3402 +static inline int
3403 +size_to_bin(int size) 
3404 +{
3405 +#if NUM_PACKET_SIZE_BINS > 1
3406 +	if (size <= packet_size_bins[0])
3407 +		return 0;
3408 +#endif
3409 +#if NUM_PACKET_SIZE_BINS > 2
3410 +	if (size <= packet_size_bins[1])
3411 +		return 1;
3412 +#endif
3413 +#if NUM_PACKET_SIZE_BINS > 3
3414 +	if (size <= packet_size_bins[2])
3415 +		return 2;
3416 +#endif
3417 +#if NUM_PACKET_SIZE_BINS > 4
3418 +#error "add support for more packet sizes"
3419 +#endif
3420 +	return NUM_PACKET_SIZE_BINS-1;
3421 +}
3422 +
3423 +static uint32_t sample_pkt_tx_time(const struct ieee80211_rate_table *rt,
3424 +	uint32_t frameLen, uint16_t rateix, int isht40, int isShortPreamble)
3425 +{
3426 +	uint8_t rate = rt->info[rateix].dot11Rate;
3427 +	uint32_t tx_time = 0;
3428 +
3429 +	if (rt->info[rateix].phy == IEEE80211_T_HT) {
3430 +    	int numStreams;
3431 +    	/* 11n frame - extract out the number of spatial streams */
3432 +    	rate |= IEEE80211_RATE_MCS;
3433 +		numStreams = HT_RC_2_STREAMS(rate);
3434 +    	KASSERT(numStreams > 0 && numStreams <= 4,
3435 +    	    ("number of spatial streams needs to be 1..3: MCS rate 0x%x!",
3436 +    	    rateix));
3437 +    	tx_time = ieee80211_compute_duration_ht(frameLen, rate, numStreams, isht40, isShortPreamble);
3438 +	} else {
3439 +    	/* Legacy rate? Return the old way */
3440 +    	rate &= IEEE80211_RATE_VAL;
3441 +    	tx_time = ieee80211_compute_duration(rt, frameLen, rate, isShortPreamble);
3442 +	}
3443 +
3444 +	return tx_time;
3445 +}
3446 +
3447 +#define WIFI_CW_MIN 31
3448 +#define WIFI_CW_MAX 1023
3449 +
3450 +/*
3451 + * Calculate the transmit duration of a frame.
3452 + */
3453 +static unsigned calc_usecs_unicast_packet(const struct ieee80211vap *vap,
3454 +				int length,
3455 +				int rix, int short_retries,
3456 +				int long_retries, int is_ht40)
3457 +{
3458 +	const struct ieee80211_rate_table *rt = ieee80211_get_ratetable(vap->iv_ic->ic_curchan);
3459 +	struct ieee80211com *ic = vap->iv_ic;
3460 +	int curmode = ieee80211_chan2mode(vap->iv_ic->ic_curchan);
3461 +	
3462 +	unsigned t_slot, t_difs, t_sifs; 
3463 +	int rts, cts;
3464 +	int tt, x, cw, cix;
3465 +
3466 +	tt = 0;
3467 +	x = 0;
3468 +	cw = WIFI_CW_MIN;
3469 +
3470 +	KASSERT(rt != NULL, ("no rate table, mode %u", curmode));
3471 +
3472 +	if (rix >= rt->rateCount) {
3473 +		printf("bogus rix %d, max %u, mode %u\n",
3474 +		       rix, rt->rateCount, curmode);
3475 +		return 0;
3476 +	}
3477 +	cix = rt->info[rix].ctlRateIndex;
3478 +	/* 
3479 +	 * XXX getting mac/phy level timings should be fixed for turbo
3480 +	 * rates, and there is probably a way to get this from the
3481 +	 * hal...
3482 +	 */
3483 +	switch (rt->info[rix].phy) {
3484 +	case IEEE80211_T_OFDM:
3485 +		t_slot = 9;
3486 +		t_sifs = 16;
3487 +		t_difs = 28;
3488 +		/* fall through */
3489 +	case IEEE80211_T_TURBO:
3490 +		t_slot = 9;
3491 +		t_sifs = 8;
3492 +		t_difs = 28;
3493 +		break;
3494 +	case IEEE80211_T_HT:
3495 +		t_slot = 9;
3496 +		t_sifs = 8;
3497 +		t_difs = 28;
3498 +		break;
3499 +	case IEEE80211_T_DS:
3500 +		/* fall through to default */
3501 +	default:
3502 +		/* pg 205 ieee.802.11.pdf */
3503 +		t_slot = 20;
3504 +		t_difs = 50;
3505 +		t_sifs = 10;
3506 +	}
3507 +
3508 +	rts = cts = 0;
3509 +
3510 +	if ((ic->ic_flags & IEEE80211_F_USEPROT) &&
3511 +	    rt->info[rix].phy == IEEE80211_T_OFDM) {
3512 +		if (ic->ic_protmode == IEEE80211_PROT_RTSCTS)
3513 +			rts = 1;
3514 +		else if (ic->ic_protmode == IEEE80211_PROT_CTSONLY)
3515 +			cts = 1;
3516 +
3517 +		int protrix;
3518 +    	if (curmode == IEEE80211_MODE_11G)
3519 +    	    protrix = rt->rateCodeToIndex[2*2];
3520 +    	else 
3521 +    	    protrix = rt->rateCodeToIndex[2*1];
3522 +    	if (0xff == protrix)
3523 +    		protrix = 0;
3524 +
3525 +		cix = rt->info[protrix].ctlRateIndex;
3526 +	}
3527 +
3528 +	if (0 /*length > ic->ic_rtsthreshold */) {
3529 +		rts = 1;
3530 +	}
3531 +
3532 +	if (rts || cts) {
3533 +		int ctsduration = 0;
3534 +
3535 +		/* NB: this is intentionally not a runtime check */
3536 +		KASSERT(cix < rt->rateCount,
3537 +		    ("bogus cix %d, max %u, mode %u\n", cix, rt->rateCount,
3538 +		     curmode));
3539 +
3540 +		if (rts)		/* SIFS + CTS */
3541 +			ctsduration += rt->info[cix].spAckDuration;
3542 +
3543 +		/* XXX assumes short preamble */
3544 +		ctsduration += sample_pkt_tx_time(rt, length, rix, is_ht40, 0);
3545 +
3546 +		if (cts)	/* SIFS + ACK */
3547 +			ctsduration += rt->info[cix].spAckDuration;
3548 +
3549 +		tt += (short_retries + 1) * ctsduration;
3550 +	}
3551 +	tt += t_difs;
3552 +
3553 +	/* XXX assumes short preamble */
3554 +	tt += (long_retries+1)*sample_pkt_tx_time(rt, length, rix, is_ht40, 0);
3555 +
3556 +	tt += (long_retries+1)*(t_sifs + rt->info[rix].spAckDuration);
3557 +
3558 +	for (x = 0; x <= short_retries + long_retries; x++) {
3559 +		cw = MIN(WIFI_CW_MAX, (cw + 1) * 2);
3560 +		tt += (t_slot * cw/2);
3561 +	}
3562 +	return tt;
3563 +}
3564 +
3565 +#endif /* _NET80211_IEEE80211_RATECTL_SAMPLE_H_ */
3566 Index: sys/net80211/ieee80211_ratectl_none.h
3567 ===================================================================
3568 --- sys/net80211/ieee80211_ratectl_none.h	(revision 0)
3569 +++ sys/net80211/ieee80211_ratectl_none.h	(revision 256825)
3570 @@ -0,0 +1,38 @@
3571 +/*-
3572 + * Copyright (c) 2013 Chenchong Qin <ccqin@FreeBSD.org>
3573 + *
3574 + * Permission to use, copy, modify, and distribute this software for any
3575 + * purpose with or without fee is hereby granted, provided that the above
3576 + * copyright notice and this permission notice appear in all copies.
3577 + *
3578 + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
3579 + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
3580 + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
3581 + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
3582 + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
3583 + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
3584 + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
3585 + */
3586 +
3587 +#ifndef _NET80211_IEEE80211_RATECTL_NONE_H_
3588 +#define _NET80211_IEEE80211_RATECTL_NONE_H_
3589 +
3590 +#include <net80211/ieee80211_ratectl.h>
3591 +
3592 +/*
3593 + * Rate control settings.
3594 + */
3595 +
3596 +struct ieee80211_none {
3597 +	struct ieee80211_rc_stat none_stat;
3598 +	/* other stuffs */
3599 +};
3600 +
3601 +/*
3602 + * Rate control state for a given node.
3603 + */
3604 +struct ieee80211_none_node {
3605 +	struct ieee80211_none *non_none;
3606 +};
3607 +
3608 +#endif /* _NET80211_IEEE80211_RATECTL_NONE_H_ */
3609 Index: sys/net80211/ieee80211_rssadapt.h
3610 ===================================================================
3611 --- sys/net80211/ieee80211_rssadapt.h	(revision 254826)
3612 +++ sys/net80211/ieee80211_rssadapt.h	(working copy)
3613 @@ -32,6 +32,8 @@
3614  #ifndef _NET80211_IEEE80211_RSSADAPT_H_
3615  #define _NET80211_IEEE80211_RSSADAPT_H_
3616  
3617 +#include <net80211/ieee80211_ratectl.h>
3618 +
3619  /* Data-rate adaptation loosely based on "Link Adaptation Strategy
3620   * for IEEE 802.11 WLAN via Received Signal Strength Measurement"
3621   * by Javier del Prado Pavon and Sunghyun Choi.
3622 @@ -43,6 +45,7 @@
3623  #define	IEEE80211_RSSADAPT_BKTPOWER	3	/* 2**_BKTPOWER */
3624  
3625  struct ieee80211_rssadapt {
3626 +	struct ieee80211_rc_stat rssadapt_stat;
3627  	const struct ieee80211vap *vap;
3628  	int	interval;			/* update interval (ticks) */
3629  };
3630 Index: sys/net80211/ieee80211_amrr.h
3631 ===================================================================
3632 --- sys/net80211/ieee80211_amrr.h	(revision 254826)
3633 +++ sys/net80211/ieee80211_amrr.h	(working copy)
3634 @@ -20,6 +20,7 @@
3635  #ifndef _NET80211_IEEE80211_AMRR_H_
3636  #define _NET80211_IEEE80211_AMRR_H_
3637  
3638 +#include <net80211/ieee80211_ratectl.h>
3639  /*-
3640   * Naive implementation of the Adaptive Multi Rate Retry algorithm:
3641   *
3642 @@ -35,6 +36,7 @@
3643  struct ieee80211vap;
3644  
3645  struct ieee80211_amrr {
3646 +	struct ieee80211_rc_stat amrr_stat;
3647  	u_int	amrr_min_success_threshold;
3648  	u_int	amrr_max_success_threshold;
3649  	int	amrr_interval;		/* update interval (ticks) */

Attached Files

To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.
  • [get | view] (2013-09-21T03:27:54+0000, 115.5 KB) [[attachment:net80211-ratectl-ath-final.diff]]
  • [get | view] (2013-09-21T03:28:13+0000, 245.4 KB) [[attachment:net80211-ratectl-debug-info.log]]
 All files | Selected Files: delete move to page copy to page

You are not allowed to attach a file to this page.