Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 5 Aug 2013 15:22:50 GMT
From:      ccqin@FreeBSD.org
To:        svn-soc-all@FreeBSD.org
Subject:   socsvn commit: r255539 - soc2013/ccqin/head/sys/net80211
Message-ID:  <201308051522.r75FMoGG021196@socsvn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: ccqin
Date: Mon Aug  5 15:22:49 2013
New Revision: 255539
URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=255539

Log:
  Add stuffs to sample_node_init and correct some errors.
  *) add ieee80211_rc_sample_txsched.h
  *) let sample_node_init setup the node
  *) correct the mix up of rt and rs
  *) add version and copyright msgs

Added:
  soc2013/ccqin/head/sys/net80211/ieee80211_rc_sample.c
     - copied, changed from r255522, soc2013/ccqin/head/sys/net80211/ieee80211_ratectl_sample.c
  soc2013/ccqin/head/sys/net80211/ieee80211_rc_sample.h
     - copied, changed from r255522, soc2013/ccqin/head/sys/net80211/ieee80211_ratectl_sample.h
  soc2013/ccqin/head/sys/net80211/ieee80211_rc_sample_txsched.h
Deleted:
  soc2013/ccqin/head/sys/net80211/ieee80211_ratectl_sample.c
  soc2013/ccqin/head/sys/net80211/ieee80211_ratectl_sample.h

Copied and modified: soc2013/ccqin/head/sys/net80211/ieee80211_rc_sample.c (from r255522, soc2013/ccqin/head/sys/net80211/ieee80211_ratectl_sample.c)
==============================================================================
--- soc2013/ccqin/head/sys/net80211/ieee80211_ratectl_sample.c	Mon Aug  5 09:58:18 2013	(r255522, copy source)
+++ soc2013/ccqin/head/sys/net80211/ieee80211_rc_sample.c	Mon Aug  5 15:22:49 2013	(r255539)
@@ -1,5 +1,6 @@
+/* $FreeBSD: head/sys/dev/ath/ath_rate/sample/sample.c 248573 2013-02-27 04:33:06Z adrian $*/
+
 /*-
- * Copyright (c) 2010 Bernhard Schmidt <bschmidt@FreeBSD.org>
  * Copyright (c) 2013 Chenchong Qin <ccqin@FreeBSD.org>
  * All rights reserved.
  *
@@ -45,7 +46,8 @@
 #include <net80211/ieee80211_var.h>
 #include <net80211/ieee80211_ht.h>
 #include <net80211/ieee80211_ratectl.h>
-#include <net80211/ieee80211_ratectl_sample.h>
+#include <net80211/ieee80211_rc_sample.h>
+#include <net80211/ieee80211_rc_sample_txsched.h>
 
 static void	sample_init(struct ieee80211vap *);
 static void	sample_deinit(struct ieee80211vap *);
@@ -79,10 +81,6 @@
 IEEE80211_RATECTL_MODULE(sample, 1);
 IEEE80211_RATECTL_ALG(sample, IEEE80211_RATECTL_SAMPLE, sample);
 
-#define	DOT11RATE(ix)	(rs->info[ix].dot11Rate & IEEE80211_RATE_VAL)
-#define	MCS(ix)		(rs->info[ix].dot11Rate | IEEE80211_RATE_MCS)
-#define	RATE(ix)	(DOT11RATE(ix) / 2)
-
 static void
 sample_init(struct ieee80211vap *vap)
 {
@@ -102,7 +100,7 @@
 	sample->sample_max_successive_failures = 3;	/* threshold for rate sampling*/
 	sample->sample_stale_failure_timeout = 10 * hz;	/* 10 seconds */
 	sample->sample_min_switch = hz;			/* 1 second */
-	sample_setinterval(vap, 500 /* ms */); 	/* actually set nothing */
+	sample_setinterval(vap, 500 /* ms */); 	/* actually do nothing */
 	sample_sysctlattach(vap, vap->iv_sysctl, vap->iv_oid);
 }
 
@@ -124,14 +122,33 @@
 	return (IEEE80211_IS_CHAN_HT(ni->ni_chan));
 }
 
+static const struct txschedule *mrr_schedules[IEEE80211_MODE_MAX+2] = {
+	NULL,		/* IEEE80211_MODE_AUTO */
+	series_11a,	/* IEEE80211_MODE_11A */
+	series_11g,	/* IEEE80211_MODE_11B */
+	series_11g,	/* IEEE80211_MODE_11G */
+	NULL,		/* IEEE80211_MODE_FH */
+	series_11a,	/* IEEE80211_MODE_TURBO_A */
+	series_11g,	/* IEEE80211_MODE_TURBO_G */
+	series_11a,	/* IEEE80211_MODE_STURBO_A */
+	series_11na,	/* IEEE80211_MODE_11NA */
+	series_11ng,	/* IEEE80211_MODE_11NG */
+	series_half,	/* IEEE80211_MODE_HALF */
+	series_quarter,	/* IEEE80211_MODE_QUARTER */
+};
+
 static void
 sample_node_init(struct ieee80211_node *ni)
 {
-	const struct ieee80211_rateset *rs = NULL;
+#define	RATE(_ix)	(ni->ni_rates.rs_rates[(_ix)] & IEEE80211_RATE_VAL)
+#define	DOT11RATE(_ix)	(rt->info[(_ix)].dot11Rate & IEEE80211_RATE_VAL)
+#define	MCS(_ix)	(ni->ni_htrates.rs_rates[_ix] | IEEE80211_RATE_MCS)
 	struct ieee80211vap *vap = ni->ni_vap;
 	struct ieee80211_sample *sample = vap->iv_rs;
-	struct ieee80211_sample_node *san;
-	uint8_t rate;
+	struct ieee80211_sample_node *san = NULL;
+	const struct ieee80211_rate_table *rt = ieee80211_get_ratetable(vap->iv_ic->ic_curchan);
+	enum ieee80211_phymode curmode = ieee80211_chan2mode(vap->iv_ic->ic_curchan);
+	int x, y, rix;
 
 	if (ni->ni_rctls == NULL) {
 		ni->ni_rctls = san = malloc(sizeof(struct ieee80211_sample_node),
@@ -145,15 +162,89 @@
 		san = ni->ni_rctls;
 	san->san_sample = sample;
 
-// XXX not done yet
+	KASSERT(rt != NULL, ("no rate table, mode %u", curmode));
+
+	san->sched = mrr_schedules[curmode];
+	KASSERT(san->sched != NULL, ("no mrr schedule for mode %u", curmode));
+
+	san->static_rix = -1;
+	sample_update_static_rix(ni);
+
+	/*
+	 * Construct a bitmask of usable rates.  This has all
+	 * negotiated rates minus those marked by the hal as
+	 * to be ignored for doing rate control.
+	 */
+	san->ratemask = 0;
+
+	/* MCS rates */
+	if (ni->ni_flags & IEEE80211_NODE_HT) {
+		for (x = 0; x < ni->ni_htrates.rs_nrates; x++) {
+			rix = rt->rateCodeToIndex[MCS(x)];
+			if (rix == 0xff)
+				continue;
+			/* skip rates marked broken by hal */
+			if (!rt->info[rix].valid)
+				continue;
+			KASSERT(rix < SAMPLE_MAXRATES,
+			    ("mcs %u has rix %d", MCS(x), rix));
+			san->ratemask |= (uint64_t) 1<<rix;
+		}
+	}
+
+	/* Legacy rates */
+	for (x = 0; x < ni->ni_rates.rs_nrates; x++) {
+		rix = rt->rateCodeToIndex[RATE(x)];
+		if (rix == 0xff)
+			continue;
+		/* skip rates marked broken by hal */
+		if (!rt->info[rix].valid)
+			continue;
+		KASSERT(rix < SAMPLE_MAXRATES,
+		    ("rate %u has rix %d", RATE(x), rix));
+		san->ratemask |= (uint64_t) 1<<rix;
+	}
+
+	for (y = 0; y < NUM_PACKET_SIZE_BINS; y++) {
+		int size = bin_to_size(y);
+		uint64_t mask;
 
-	san->san_success = 0;
-	san->san_recovery = 0;
-	san->san_txcnt = san->san_retrycnt = 0;
-	san->san_success_threshold = sample->sample_min_success_threshold;
+		san->packets_sent[y] = 0;
+		san->current_sample_rix[y] = -1;
+		san->last_sample_rix[y] = 0;
+		/* XXX start with first valid rate */
+		san->current_rix[y] = ffs(san->ratemask)-1;
+		
+		/*
+		 * Initialize the statistics buckets; these are
+		 * indexed by the rate code index.
+		 */
+		for (rix = 0, mask = san->ratemask; mask != 0; rix++, mask >>= 1) {
+			if ((mask & 1) == 0)		/* not a valid rate */
+				continue;
+			san->stats[y][rix].successive_failures = 0;
+			san->stats[y][rix].tries = 0;
+			san->stats[y][rix].total_packets = 0;
+			san->stats[y][rix].packets_acked = 0;
+			san->stats[y][rix].last_tx = 0;
+			san->stats[y][rix].ewma_pct = 0;
+			
+			san->stats[y][rix].perfect_tx_time =
+			    calc_usecs_unicast_packet(size, rix, 0, 0,
+			    (ni->ni_chw == 40));
+			san->stats[y][rix].average_tx_time =
+			    san->stats[y][rix].perfect_tx_time;
+		}
+	}
 
-// XXX not done yet
-	ni->ni_txrate = ni->ni_rates.rs_rates[0] & IEEE80211_RATE_VAL;
+	/* set the visible bit-rate */
+	if (san->static_rix != -1)
+		ni->ni_txrate = DOT11RATE(san->static_rix);
+	else
+		ni->ni_txrate = RATE(0);
+#undef RATE
+#undef DOT11RATE
+#undef MCS
 }
 
 static void
@@ -163,20 +254,20 @@
 }
 
 static int
-dot11rate(const ieee80211_rateset *rs, int rix)
+dot11rate(const ieee80211_rate_table *rt, int rix)
 {
 	if (rix < 0)
 		return -1;
-	return rs->info[rix].phy == IEEE80211_T_HT ?
-	    rs->info[rix].dot11Rate : (rs->info[rix].dot11Rate & IEEE80211_RATE_VAL) / 2;
+	return rt->info[rix].phy == IEEE80211_T_HT ?
+	    rt->info[rix].dot11Rate : (rt->info[rix].dot11Rate & IEEE80211_RATE_VAL) / 2;
 }
 
 static const char *
-dot11rate_label(const ieee80211_rateset *rs, int rix)
+dot11rate_label(const ieee80211_rate_table *rt, int rix)
 {
 	if (rix < 0)
 		return "";
-	return rs->info[rix].phy == IEEE80211_T_HT ? "MCS" : "Mb ";
+	return rt->info[rix].phy == IEEE80211_T_HT ? "MCS" : "Mb ";
 }
 
 /*
@@ -184,7 +275,7 @@
  * or -1 if all the average_tx_times are 0.
  */
 static __inline int
-pick_best_rate(const struct ieee80211_node *ni, const struct ieee80211_rateset *rs,
+pick_best_rate(const struct ieee80211_node *ni, const struct ieee80211_rate_table *rt,
     int size_bin, int require_acked_before)
 {
 	struct ieee80211_sample_node *san = ni->ni_rctls;
@@ -201,8 +292,8 @@
 			continue;
 
 		/* Don't pick a non-HT rate for a HT node */
-		if ((ni.ni_flags & IEEE80211_NODE_HT) &&
-		    (rs->info[rix].phy != IEEE80211_T_HT)) {
+		if ((ni->ni_flags & IEEE80211_NODE_HT) &&
+		    (rt->info[rix].phy != IEEE80211_T_HT)) {
 			continue;
 		}
 
@@ -232,7 +323,7 @@
 		 * eliminate rates that are going to be obviously
 		 * worse.
 		 */
-		if (ni.ni_flags & IEEE80211_NODE_HT) {
+		if (ni->ni_flags & IEEE80211_NODE_HT) {
 			if (best_rate_pct > (pct + 50))
 				continue;
 		}
@@ -241,7 +332,7 @@
 		 * For non-MCS rates, use the current average txtime for
 		 * comparison.
 		 */
-		if (! (ni.ni_flags & IEEE80211_NODE_HT)) {
+		if (! (ni->ni_flags & IEEE80211_NODE_HT)) {
 			if (best_rate_tt == 0 || tt <= best_rate_tt) {
 				best_rate_tt = tt;
 				best_rate_rix = rix;
@@ -254,7 +345,7 @@
 		 * allow a little bit of leeway. This should later
 		 * be abstracted out and properly handled.
 		 */
-		if (ni.ni_flags & IEEE80211_NODE_HT) {
+		if (ni->ni_flags & IEEE80211_NODE_HT) {
 			if (best_rate_tt == 0 || (tt * 8 <= best_rate_tt * 10)) {
 				best_rate_tt = tt;
 				best_rate_rix = rix;
@@ -269,9 +360,11 @@
  * Pick a good "random" bit-rate to sample other than the current one.
  */
 static __inline int
-pick_sample_rate(const struct ieee80211_node *ni, const ieee80211_rateset *rs, 
+pick_sample_rate(const struct ieee80211_node *ni, const ieee80211_rate_table *rt, 
 	int size_bin)
 {
+#define	DOT11RATE(ix)	(rt->info[ix].dot11Rate & IEEE80211_RATE_VAL)
+#define	MCS(ix)		(rt->info[ix].dot11Rate | IEEE80211_RATE_MCS)
 	struct ieee80211_sample_node *san = ni->ni_rctls;
 	struct ieee80211_sample *sample = san->san_sample;
 	int current_rix, rix;
@@ -292,7 +385,7 @@
 	while (mask != 0) {
 		if ((mask & ((uint64_t) 1<<rix)) == 0) {	/* not a supported rate */
 	nextrate:
-			if (++rix >= rs->rateCount)
+			if (++rix >= rt->rateCount)
 				rix = 0;
 			continue;
 		}
@@ -314,8 +407,8 @@
 		 */
 #if 1
 		/* if the node is HT and the rate isn't HT, don't bother sample */
-		if ((ni.ni_flags & IEEE80211_NODE_HT) &&
-		    (rs->info[rix].phy != IEEE80211_T_HT)) {
+		if ((ni->ni_flags & IEEE80211_NODE_HT) &&
+		    (rt->info[rix].phy != IEEE80211_T_HT)) {
 			mask &= ~((uint64_t) 1<<rix);
 			goto nextrate;
 		}
@@ -338,7 +431,7 @@
 		 * For HT, only sample a few rates on either side of the
 		 * current rix; there's quite likely a lot of them.
 		 */
-		if (ni.ni_flags & IEEE80211_NODE_HT) {
+		if (ni->ni_flags & IEEE80211_NODE_HT) {
 			if (rix < (current_rix - 3) ||
 			    rix > (current_rix + 3)) {
 				mask &= ~((uint64_t) 1<<rix);
@@ -347,7 +440,7 @@
 		}
 
 		/* Don't sample more than 2 rates higher for rates > 11M for non-HT rates */
-		if (! (ni.ni_flags & IEEE80211_NODE_HT)) {
+		if (! (ni->ni_flags & IEEE80211_NODE_HT)) {
 			if (DOT11RATE(rix) > 2*11 && rix > current_rix + 2) {
 				mask &= ~((uint64_t) 1<<rix);
 				goto nextrate;
@@ -358,15 +451,34 @@
 		return rix;
 	}
 	return current_rix;
+#undef DOT11RATE
+#undef MCS
 }
 
 static int
 sample_get_static_rix(const struct ieee80211_node *ni)
 {
+#define	RATE(_ix)	(ni->ni_rates.rs_rates[(_ix)] & IEEE80211_RATE_VAL)
+#define	MCS(_ix)	(ni->ni_htrates.rs_rates[_ix] | IEEE80211_RATE_MCS)
+	struct ieee80211vap *vap = ni->ni_vap;
+	const struct ieee80211_rate_table *rt = ieee80211_get_ratetable(vap->iv_ic->ic_curchan);
 	const struct ieee80211_txparam *tp = ni->ni_txparms;
-	const struct ieee80211_rateset *rs = sample_get_rateset(ni);
-	
-	return rs->rateCodeToIndex[tp->ucastrate];
+	int srate;
+
+	/* Check MCS rates */
+	for (srate = ni->ni_htrates.rs_nrates - 1; srate >= 0; srate--) {
+		if (MCS(srate) == tp->ucastrate)
+			return rt->rateCodeToIndex[tp->ucastrate];
+	}
+
+	/* Check legacy rates */
+	for (srate = ni->ni_rates.rs_nrates - 1; srate >= 0; srate--) {
+		if (RATE(srate) == tp->ucastrate)
+			return rt->rateCodeToIndex[tp->ucastrate];
+	}
+	return -1;
+#undef	RATE
+#undef	MCS
 }
 
 static void
@@ -395,19 +507,21 @@
 static int
 sample_pick_seed_rate_legacy(const struct ieee80211_node *ni, int frameLen)
 {
+#define	DOT11RATE(ix)	(rt->info[ix].dot11Rate & IEEE80211_RATE_VAL)
+	struct ieee80211vap *vap = ni->ni_vap;
 	struct ieee80211_sample_node *san = ni->ni_rctls;
-	const struct ieee80211_rateset *rs = &ni->ni_rates;
+	const struct ieee80211_rate_table *rt = ieee80211_get_ratetable(vap->iv_ic->ic_curchan);
 	
 	const int size_bin = size_to_bin(frameLen);
 	int rix = -1;
 
 	/* no packet has been sent successfully yet */
-	for (rix = rs->rateCount-1; rix > 0; rix--) {
+	for (rix = rt->rateCount-1; rix > 0; rix--) {
 		if ((san->ratemask & ((uint64_t) 1<<rix)) == 0)
 			continue;
 
 		/* Skip HT rates */
-		if (rs->info[rix].phy == IEEE80211_T_HT)
+		if (rt->info[rix].phy == IEEE80211_T_HT)
 			continue;
 
 		/*
@@ -420,6 +534,7 @@
 		}
 	}
 	return rix;
+#undef DOT11RATE
 }
 
 /*
@@ -430,24 +545,26 @@
 static int
 sample_pick_seed_rate_ht(const struct ieee80211_node *ni, int frameLen)
 {
+#define	MCS(ix)		(rt->info[ix].dot11Rate | IEEE80211_RATE_MCS)
+	struct ieee80211vap *vap = ni->ni_vap;
 	struct ieee80211_sample_node *san = ni->ni_rctls;
-	const struct ieee80211_rateset *rs = (struct ieee80211_rateset *) &ni->ni_htrates;
+	const struct ieee80211_rate_table *rt = ieee80211_get_ratetable(vap->iv_ic->ic_curchan);
 	
 	const int size_bin = size_to_bin(frameLen);
 	int rix = -1, ht_rix = -1;
 
 	/* no packet has been sent successfully yet */
-	for (rix = rs->rateCount-1; rix > 0; rix--) {
+	for (rix = rt->rateCount-1; rix > 0; rix--) {
 		/* Skip rates we can't use */
 		if ((san->ratemask & ((uint64_t) 1<<rix)) == 0)
 			continue;
 
 		/* Keep a copy of the last seen HT rate index */
-		if (rs->info[rix].phy == IEEE80211_T_HT)
+		if (rt->info[rix].phy == IEEE80211_T_HT)
 			ht_rix = rix;
 
 		/* Skip non-HT rates */
-		if (rs->info[rix].phy != IEEE80211_T_HT)
+		if (rt->info[rix].phy != IEEE80211_T_HT)
 			continue;
 
 		/*
@@ -466,6 +583,7 @@
 	 * > 0; otherwise use the lowest MCS rix (hopefully MCS 0.)
 	 */
 	return MAX(rix, ht_rix);
+#undef MCS
 }
 
 static const struct ieee80211_rateset *
@@ -489,26 +607,24 @@
 static int
 sample_rate(struct ieee80211_node *ni, void *arg __unused, uint32_t iarg __unused)
 {
+#define	DOT11RATE(ix)	(rt->info[ix].dot11Rate & IEEE80211_RATE_VAL)
+#define	MCS(ix)		(rt->info[ix].dot11Rate | IEEE80211_RATE_MCS)
+#define	RATE(ix)	(DOT11RATE(ix) / 2)
+	struct ieee80211vap *vap = ni->ni_vap;
 	struct ieee80211_sample_node *san = ni->ni_rctls;
 	struct ieee80211_sample *sample = san->san_sample;
-	size_t frameLen = (size_t)iarg;
-
-	const struct ieee80211vap *vap = ni->ni_vap;
-	struct ifnet *ifp = vap->iv_ifp;
-	struct ieee80211com *ic = ifp->if_l2com;
-
+	const struct ieee80211_rate_table *rt = ieee80211_get_ratetable(vap->iv_ic->ic_curchan);
+	
 	int rix, mrr, best_rix, change_rates;
 	unsigned average_tx_time;
 	
-	const struct ieee80211_rateset *rs = sample_get_rateset(ni);
-
+	size_t frameLen = (size_t)iarg;
 	const int size_bin = size_to_bin(frameLen);
 
 	sample_update_static_rix(ni);
 
-
 	if (san->static_rix != -1) {
-		rix = sn->static_rix;
+		rix = san->static_rix;
 		goto done;
 	}
 
@@ -517,8 +633,7 @@
 	if (!(vap->iv_rate->ir_capabilities & IEEE80211_RATECTL_CAP_MRRPROT))
 		mrr = 0;
 
-	// XXX not done here.
-	best_rix = pick_best_rate(ni, rs, size_bin, !mrr);
+	best_rix = pick_best_rate(ni, rt, size_bin, !mrr);
 	if (best_rix >= 0) {
 		average_tx_time = san->stats[size_bin][best_rix].average_tx_time;
 	} else {
@@ -529,19 +644,18 @@
 	 * Limit the time measuring the performance of other tx
 	 * rates to sample_rate% of the total transmission time.
 	 */
-	if (san->sample_tt[size_bin] < average_tx_time * (san->packets_since_sample[size_bin]*sample->sample_rate/100)) {
-		// XXX not done here.
-		rix = pick_sample_rate(ni, rs, size_bin);
-		// XXX
-		IEEE80211_NOTE(ni.ni_vap, IEEE80211_MSG_RATECTL,
+	if (san->sample_tt[size_bin] < average_tx_time * (san->packets_since_sample[size_bin] *
+		sample->sample_rate/100)) {
+		rix = pick_sample_rate(ni, rt, size_bin);
+		IEEE80211_NOTE(vap, IEEE80211_MSG_RATECTL,
 		     &ni, "att %d sample_tt %d size %u sample rate %d %s current rate %d %s",
 		     average_tx_time,
 		     san->sample_tt[size_bin],
 		     bin_to_size(size_bin),
-		     dot11rate(rs, rix),
-		     dot11rate_label(rs, rix),
-		     dot11rate(rs, san->current_rix[size_bin]),
-		     dot11rate_label(rs, san->current_rix[size_bin]));
+		     dot11rate(rt, rix),
+		     dot11rate_label(rt, rix),
+		     dot11rate(rt, san->current_rix[size_bin]),
+		     dot11rate_label(rt, san->current_rix[size_bin]));
 		if (rix != san->current_rix[size_bin]) {
 			san->current_sample_rix[size_bin] = rix;
 		} else {
@@ -553,37 +667,33 @@
 		if (!san->packets_sent[size_bin] || best_rix == -1) {
 			/* no packet has been sent successfully yet */
 			change_rates = 1;
-			if (ni.ni_flags & IEEE80211_NODE_HT)
-				best_rix = //XXX
-				    sample_pick_seed_rate_ht(ni, frameLen);
+			if (ni->ni_flags & IEEE80211_NODE_HT)
+				best_rix = sample_pick_seed_rate_ht(ni, frameLen);
 			else
-				best_rix = // XXX
-				    sample_pick_seed_rate_legacy(ni, frameLen);
+				best_rix = sample_pick_seed_rate_legacy(ni, frameLen);
 		} else if (san->packets_sent[size_bin] < 20) {
 			/* let the bit-rate switch quickly during the first few packets */
-			IEEE80211_NOTE(ni.ni_vap,
+			IEEE80211_NOTE(vap,
 			    IEEE80211_MSG_RATECTL, &ni,
 			    "%s: switching quickly..", __func__);
 			change_rates = 1;
 		} else if (ticks - sample->sample_min_switch > san->ticks_since_switch[size_bin]) {
 			/* min_switch seconds have gone by */
-			// XXX
 			IEEE80211_NOTE(vap,
 			    IEEE80211_MSG_RATECTL, &ni,
 			    "%s: min_switch %d > ticks_since_switch %d..",
 			    __func__, ticks - sample->sample_min_switch, san->ticks_since_switch[size_bin]);
 			change_rates = 1;
-		} else if ((! (ni.ni_flags & IEEE80211_NODE_HT)) &&
+		} else if ((! (ni->ni_flags & IEEE80211_NODE_HT)) &&
 		    (2*average_tx_time < san->stats[size_bin][san->current_rix[size_bin]].average_tx_time)) {
 			/* the current bit-rate is twice as slow as the best one */
-			// XXX
 			IEEE80211_NOTE(vap,
 			    IEEE80211_MSG_RATECTL, &ni,
 			    "%s: 2x att (= %d) < cur_rix att %d",
 			    __func__,
 			    2 * average_tx_time, san->stats[size_bin][san->current_rix[size_bin]].average_tx_time);
 			change_rates = 1;
-		} else if ((ni.ni_flags & IEEE80211_NODE_HT)) {
+		} else if ((ni->ni_flags & IEEE80211_NODE_HT)) {
 			int cur_rix = san->current_rix[size_bin];
 			int cur_att = san->stats[size_bin][cur_rix].average_tx_time;
 			/*
@@ -612,7 +722,6 @@
 		
 		if (change_rates) {
 			if (best_rix != san->current_rix[size_bin]) {
-				// XXX
 				IEEE80211_NOTE(vap,
 				    IEEE80211_MSG_RATECTL,
 				    &ni,
@@ -634,7 +743,7 @@
 			/* 
 			 * Set the visible txrate for this node.
 			 */
-			ni.ni_txrate = (rs->info[best_rix].phy == IEEE80211_T_HT) ?  MCS(best_rix) : DOT11RATE(best_rix);
+			ni->ni_txrate = dot11rate(rt, best_rix);
 		}
 		rix = san->current_rix[size_bin];
 		san->packets_since_switch[size_bin]++;
@@ -648,21 +757,24 @@
 	 * For now though, let's not panic, so we can start to figure
 	 * out how to better reproduce it.
 	 */
-	if (rix < 0 || rix >= rs->rateCount) {
+	if (rix < 0 || rix >= rt->rateCount) {
 		printf("%s: ERROR: rix %d out of bounds (rateCount=%d)\n",
 		    __func__,
 		    rix,
-		    rs->rateCount);
+		    rt->rateCount);
 		    rix = 0;	/* XXX just default for now */
 	}
-	KASSERT(rix >= 0 && rix < rs->rateCount, ("rix is %d", rix));
+	KASSERT(rix >= 0 && rix < rt->rateCount, ("rix is %d", rix));
 
 	// *rix0 = rix;
-	// *txrate = rs->info[rix].rateCode
-	// 	| (shortPreamble ? rs->info[rix].shortPreamble : 0);
+	// *txrate = rt->info[rix].rateCode
+	// 	| (shortPreamble ? rt->info[rix].shortPreamble : 0);
 	san->packets_sent[size_bin]++;
 
 	return rix;
+#undef DOT11RATE
+#undef MCS
+#undef RATE
 }
 
 static void
@@ -694,29 +806,29 @@
 static void
 sample_stats(void *arg, struct ieee80211_node *ni)
 {
+	struct ieee80211vap *vap = ni->ni_vap;
 	struct ieee80211_sample_node *san = ni->ni_rctls;
-	// XXX sc->sc_currates
-	const ieee80211_rateset *rs = sample_get_rateset(ni); 
+	const struct ieee80211_rate_table *rt = ieee80211_get_ratetable(vap->iv_ic->ic_curchan);
 	uint64_t mask;
 	int rix, y;
 
 	printf("\n[%s] refcnt %d static_rix (%d %s) ratemask 0x%jx\n",
 	    ether_sprintf(ni->ni_macaddr), ieee80211_node_refcnt(ni),
-	    dot11rate(rs, san->static_rix),
-	    dot11rate_label(rs, san->static_rix),
+	    dot11rate(rt, san->static_rix),
+	    dot11rate_label(rt, san->static_rix),
 	    (uintmax_t)san->ratemask);
 	for (y = 0; y < NUM_PACKET_SIZE_BINS; y++) {
 		printf("[%4u] cur rix %d (%d %s) since switch: packets %d ticks %u\n",
 		    bin_to_size(y), san->current_rix[y],
-		    dot11rate(rs, san->current_rix[y]),
-		    dot11rate_label(rs, san->current_rix[y]),
+		    dot11rate(rt, san->current_rix[y]),
+		    dot11rate_label(rt, san->current_rix[y]),
 		    san->packets_since_switch[y], san->ticks_since_switch[y]);
 		printf("[%4u] last sample (%d %s) cur sample (%d %s) packets sent %d\n",
 		    bin_to_size(y),
-		    dot11rate(rs, san->last_sample_rix[y]),
-		    dot11rate_label(rs, san->last_sample_rix[y]),
-		    dot11rate(rs, san->current_sample_rix[y]),
-		    dot11rate_label(rs, san->current_sample_rix[y]),
+		    dot11rate(rt, san->last_sample_rix[y]),
+		    dot11rate_label(rt, san->last_sample_rix[y]),
+		    dot11rate(rt, san->current_sample_rix[y]),
+		    dot11rate_label(rt, san->current_sample_rix[y]),
 		    san->packets_sent[y]);
 		printf("[%4u] packets since sample %d sample tt %u\n",
 		    bin_to_size(y), san->packets_since_sample[y],
@@ -729,7 +841,7 @@
 			if (san->stats[y][rix].total_packets == 0)
 				continue;
 			printf("[%2u %s:%4u] %8ju:%-8ju (%3d%%) (EWMA %3d.%1d%%) T %8ju F %4d avg %5u last %u\n",
-			    dot11rate(rs, rix), dot11rate_label(rs, rix),
+			    dot11rate(rt, rix), dot11rate_label(rt, rix),
 			    bin_to_size(y),
 			    (uintmax_t) san->stats[y][rix].total_packets,
 			    (uintmax_t) san->stats[y][rix].packets_acked,
@@ -812,7 +924,3 @@
 	    "sample_stats", CTLTYPE_INT | CTLFLAG_RW, vap, 0,
 	    sample_sysctl_stats, "I", "sample: print statistics");
 }
-
-#undef DOT11RATE
-#undef MCS
-#undef RATE
\ No newline at end of file

Copied and modified: soc2013/ccqin/head/sys/net80211/ieee80211_rc_sample.h (from r255522, soc2013/ccqin/head/sys/net80211/ieee80211_ratectl_sample.h)
==============================================================================
--- soc2013/ccqin/head/sys/net80211/ieee80211_ratectl_sample.h	Mon Aug  5 09:58:18 2013	(r255522, copy source)
+++ soc2013/ccqin/head/sys/net80211/ieee80211_rc_sample.h	Mon Aug  5 15:22:49 2013	(r255539)
@@ -1,5 +1,6 @@
+/* $FreeBSD: head/sys/dev/ath/ath_rate/sample/sample.h 240382 2012-08-15 07:10:10Z adrian $*/
+
 /*-
- * Copyright (c) 2005 John Bicket
  * Copyright (c) 2013 Chenchong Qin <ccqin@FreeBSD.org>
  * All rights reserved.
  *
@@ -138,4 +139,14 @@
 	return NUM_PACKET_SIZE_BINS-1;
 }
 
+/*
+ * Calculate the transmit duration of a frame.
+ */
+static unsigned calc_usecs_unicast_packet(int length,
+				int rix, int short_retries,
+				int long_retries, int is_ht40)
+{
+	/* XXX not done yet */
+}
+
 #endif /* _NET80211_IEEE80211_RATECTL_SAMPLE_H_ */

Added: soc2013/ccqin/head/sys/net80211/ieee80211_rc_sample_txsched.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ soc2013/ccqin/head/sys/net80211/ieee80211_rc_sample_txsched.h	Mon Aug  5 15:22:49 2013	(r255539)
@@ -0,0 +1,241 @@
+/* $FreeBSD: head/sys/dev/ath/ath_rate/sample/tx_schedules.h 240384 2012-08-15 07:50:42Z adrian $*/
+
+/*-
+ * Copyright (c) 2005 John Bicket
+ * Copyright (c) 2013 Chenchong Qin <ccqin@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer,
+ *    without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
+ *    redistribution must be conditioned upon including a substantially
+ *    similar Disclaimer requirement for further binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ *    of any contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ */
+#ifndef	__ATH_RATE_SAMPLE_TXSCHEDULES_H__
+#define	__ATH_RATE_SAMPLE_TXSCHEDULES_H__
+
+#include <sys/cdefs.h>
+
+#define A(_r) \
+    (((_r) == 6)   ? 0 : (((_r) == 9)   ? 1 : (((_r) == 12)  ? 2 : \
+    (((_r) == 18)  ? 3 : (((_r) == 24)  ? 4 : (((_r) == 36)  ? 5 : \
+    (((_r) == 48)  ? 6 : (((_r) == 54)  ? 7 : 0))))))))
+static const struct txschedule series_11a[] = {
+	{ 3,A( 6), 3,A(  6), 0,A(  6), 0,A( 6) },	/*   6Mb/s */
+	{ 4,A( 9), 3,A(  6), 4,A(  6), 0,A( 6) },	/*   9Mb/s */
+	{ 4,A(12), 3,A(  6), 4,A(  6), 0,A( 6) },	/*  12Mb/s */
+	{ 4,A(18), 3,A( 12), 4,A(  6), 2,A( 6) },	/*  18Mb/s */
+	{ 4,A(24), 3,A( 18), 4,A( 12), 2,A( 6) },	/*  24Mb/s */
+	{ 4,A(36), 3,A( 24), 4,A( 18), 2,A( 6) },	/*  36Mb/s */
+	{ 4,A(48), 3,A( 36), 4,A( 24), 2,A(12) },	/*  48Mb/s */
+	{ 4,A(54), 3,A( 48), 4,A( 36), 2,A(24) }	/*  54Mb/s */
+};
+
+#define NA1(_r) \
+	(((_r) == 6.5)  ? 8 : (((_r) == 13)  ?  9 : (((_r) == 19.5)? 10 : \
+	(((_r) == 26)  ? 11 : (((_r) == 39)  ? 12 : (((_r) == 52)  ? 13 : \
+	(((_r) == 58.5)? 14 : (((_r) == 65)  ? 15 : 0))))))))
+#define NA2(_r) \
+	(((_r) == 13) ? 16 : (((_r) == 26) ? 17 : (((_r) == 39) ? 18 : \
+	(((_r) == 52) ? 19 : (((_r) == 78) ? 20 : (((_r) == 104)? 21 : \
+	(((_r) == 117)? 22 : (((_r) == 130)? 23 : 0))))))))
+#define NA3(_r) \
+	(((_r) == 19.5)  ? 24 : (((_r) == 39) ? 25 : (((_r) == 58.5)  ? 26 : \
+	(((_r) == 78)  ? 27 : (((_r) == 117) ? 28 : (((_r) == 156) ? 29 : \
+	(((_r) == 175.5) ? 30 : (((_r) == 195)? 31 : 0))))))))
+static const struct txschedule series_11na[] = {
+	{ 3,A( 6), 3,A(  6), 0,A(  6), 0,A( 6) },       /*   6Mb/s */
+	{ 4,A( 9), 3,A(  6), 4,A(  6), 0,A( 6) },       /*   9Mb/s */
+	{ 4,A(12), 3,A(  6), 4,A(  6), 0,A( 6) },       /*  12Mb/s */
+	{ 4,A(18), 3,A( 12), 4,A(  6), 2,A( 6) },       /*  18Mb/s */
+	{ 4,A(24), 3,A( 18), 4,A( 12), 2,A( 6) },       /*  24Mb/s */
+	{ 4,A(36), 3,A( 24), 4,A( 18), 2,A( 6) },       /*  36Mb/s */
+	{ 4,A(48), 3,A( 36), 4,A( 24), 2,A(12) },       /*  48Mb/s */
+	{ 4,A(54), 3,A( 48), 4,A( 36), 2,A(24) },       /*  54Mb/s */
+
+	/* 1 stream rates */
+
+	{ 3,NA1( 6.5), 3,NA1( 6.5), 0,NA1( 6.5), 0,NA1(6.5) },  /* 6.5Mb/s */
+	{ 4,NA1(  13), 3,NA1( 6.5), 4,NA1( 6.5), 0,NA1(6.5) },  /*  13Mb/s */
+	{ 4,NA1(19.5), 3,NA1( 6.5), 4,NA1( 6.5), 0,NA1(6.5) },  /*19.5Mb/s */
+	{ 4,NA1(  26), 3,NA1(19.5), 4,NA1( 6.5), 2,NA1(6.5) },  /*  26Mb/s */
+	{ 4,NA1(  39), 3,NA1(  26), 4,NA1(19.5), 2,NA1(6.5) },  /*  39Mb/s */
+	{ 4,NA1(  52), 3,NA1(  39), 4,NA1(  26), 2,NA1(6.5) },  /*  52Mb/s */
+	{ 4,NA1(58.5), 3,NA1(  52), 4,NA1(  39), 2,NA1( 13) },  /*58.5Mb/s */
+	{ 4,NA1(  65), 3,NA1(58.5), 4,NA1(  52), 2,NA1( 13) },  /*  65Mb/s */
+
+	/* 2 stream rates */
+
+	{ 3,NA2(  13), 3,NA2(  13), 0,NA2(  13), 0,NA2( 13) },  /*  13Mb/s */
+	{ 4,NA2(  26), 3,NA2(  13), 4,NA2(  13), 0,NA2( 13) },  /*  26Mb/s */
+	{ 4,NA2(  39), 3,NA2(  26), 4,NA2(  13), 2,NA2( 13) },  /*  39Mb/s */
+	{ 4,NA2(  52), 3,NA2(  39), 4,NA2(  26), 2,NA2( 13) },  /*  52Mb/s */
+	{ 4,NA2(  78), 3,NA2(  52), 4,NA2(  39), 2,NA2( 13) },  /*  78Mb/s */
+	{ 4,NA2( 104), 3,NA2(  78), 4,NA2(  52), 2,NA2( 13) },  /* 104Mb/s */
+	{ 4,NA2( 117), 3,NA2( 104), 4,NA2(  78), 2,NA2( 26) },  /* 117Mb/s */
+	{ 4,NA2( 130), 3,NA2( 117), 4,NA2( 104), 2,NA2( 26) },   /* 130Mb/s */
+
+	/* 3 stream rates */
+
+	{ 3,NA3(19.5), 3,NA3(19.5), 0,NA3(19.5), 0,NA3(19.5) },  /*  19Mb/s */
+	{ 3,NA3(  39), 3,NA3(19.5), 0,NA3(19.5), 0,NA3(19.5) },  /*  39Mb/s */
+	{ 3,NA3(58.5), 3,NA3(  39), 0,NA3(19.5), 0,NA3(19.5) },  /*  58Mb/s */
+	{ 3,NA3(  78), 3,NA3(58.5), 0,NA3(  39), 0,NA3(19.5) },  /*  78Mb/s */
+	{ 3,NA3( 117), 3,NA3(  78), 0,NA3(58.5), 0,NA3(19.5) },  /* 117Mb/s */
+	{ 3,NA3( 156), 3,NA3( 117), 0,NA3(  78), 0,NA3(19.5) },  /*  156Mb/s */
+	{ 3,NA3(175.5), 3,NA3( 156), 0,NA3( 117), 0,NA3(  39) },  /*  175Mb/s */
+	{ 3,NA3( 195), 3,NA3( 195), 0,NA3( 156), 0,NA3(58.5) },  /* 195Mb/s */
+};
+#undef A
+#undef NA3
+#undef NA2
+#undef NA1
+
+#define G(_r) \
+    (((_r) == 1)   ? 0 : (((_r) == 2)   ? 1 : (((_r) == 5.5) ? 2 : \
+    (((_r) == 11)  ? 3 : (((_r) == 6)   ? 4 : (((_r) == 9)   ? 5 : \
+    (((_r) == 12)  ? 6 : (((_r) == 18)  ? 7 : (((_r) == 24)  ? 8 : \
+    (((_r) == 36)  ? 9 : (((_r) == 48)  ? 10 : (((_r) == 54)  ? 11 : 0))))))))))))
+static const struct txschedule series_11g[] = {
+	{ 3,G( 1), 3,G(  1), 0,G(  1), 0,G( 1) },	/*   1Mb/s */
+	{ 4,G( 2), 3,G(  1), 4,G(  1), 0,G( 1) },	/*   2Mb/s */
+	{ 4,G(5.5),3,G(  2), 4,G(  1), 2,G( 1) },	/* 5.5Mb/s */
+	{ 4,G(11), 3,G(5.5), 4,G(  2), 2,G( 1) },	/*  11Mb/s */
+	{ 4,G( 6), 3,G(5.5), 4,G(  2), 2,G( 1) },	/*   6Mb/s */
+	{ 4,G( 9), 3,G(  6), 4,G(5.5), 2,G( 1) },	/*   9Mb/s */
+	{ 4,G(12), 3,G( 11), 4,G(5.5), 2,G( 1) },	/*  12Mb/s */
+	{ 4,G(18), 3,G( 12), 4,G( 11), 2,G( 1) },	/*  18Mb/s */
+	{ 4,G(24), 3,G( 18), 4,G( 12), 2,G( 1) },	/*  24Mb/s */
+	{ 4,G(36), 3,G( 24), 4,G( 18), 2,G( 1) },	/*  36Mb/s */
+	{ 4,G(48), 3,G( 36), 4,G( 24), 2,G( 1) },	/*  48Mb/s */
+	{ 4,G(54), 3,G( 48), 4,G( 36), 2,G( 1) }	/*  54Mb/s */
+};
+
+#define NG1(_r) \
+	(((_r) == 6.5) ? 12 : (((_r) == 13) ? 13 : (((_r) == 19.5)? 14 : \
+	(((_r) == 26)  ? 15 : (((_r) == 39) ? 16 : (((_r) == 52)  ? 17 : \
+	(((_r) == 58.5)? 18 : (((_r) == 65) ? 19 : 0))))))))
+#define NG2(_r) \
+	(((_r) == 13)  ? 20 : (((_r) == 26) ? 21 : (((_r) == 39)  ? 22 : \
+	(((_r) == 52)  ? 23 : (((_r) == 78) ? 24 : (((_r) == 104) ? 25 : \
+	(((_r) == 117) ? 26 : (((_r) == 130)? 27 : 0))))))))
+#define NG3(_r) \
+	(((_r) == 19.5)  ? 28 : (((_r) == 39) ? 29 : (((_r) == 58.5)  ? 30 : \
+	(((_r) == 78)  ? 31 : (((_r) == 117) ? 32 : (((_r) == 156) ? 33 : \
+	(((_r) == 175.5) ? 34 : (((_r) == 195)? 35 : 0))))))))
+
+static const struct txschedule series_11ng[] = {
+	{ 3,G( 1), 3,G(  1), 0,G(  1), 0,G( 1) },       /*   1Mb/s */
+	{ 4,G( 2), 3,G(  1), 4,G(  1), 0,G( 1) },       /*   2Mb/s */
+	{ 4,G(5.5),3,G(  2), 4,G(  1), 2,G( 1) },       /* 5.5Mb/s */
+	{ 4,G(11), 3,G(5.5), 4,G(  2), 2,G( 1) },       /*  11Mb/s */
+	{ 4,G( 6), 3,G(5.5), 4,G(  2), 2,G( 1) },       /*   6Mb/s */
+	{ 4,G( 9), 3,G(  6), 4,G(5.5), 2,G( 1) },       /*   9Mb/s */
+	{ 4,G(12), 3,G( 11), 4,G(5.5), 2,G( 1) },       /*  12Mb/s */
+	{ 4,G(18), 3,G( 12), 4,G( 11), 2,G( 1) },       /*  18Mb/s */
+	{ 4,G(24), 3,G( 18), 4,G( 12), 2,G( 1) },       /*  24Mb/s */
+	{ 4,G(36), 3,G( 24), 4,G( 18), 2,G( 1) },       /*  36Mb/s */
+	{ 4,G(48), 3,G( 36), 4,G( 24), 2,G( 1) },       /*  48Mb/s */
+	{ 4,G(54), 3,G( 48), 4,G( 36), 2,G( 1) },       /*  54Mb/s */
+
+	/* 1 stream rates */
+
+	{ 3,NG1( 6.5), 3,NG1( 6.5), 0,NG1( 6.5), 0,NG1(6.5) },  /* 6.5Mb/s */
+	{ 4,NG1(  13), 3,NG1( 6.5), 4,NG1( 6.5), 0,NG1(6.5) },  /*  13Mb/s */
+	{ 4,NG1(19.5), 3,NG1( 6.5), 4,NG1( 6.5), 0,NG1(6.5) },  /*19.5Mb/s */
+	{ 4,NG1(  26), 3,NG1(19.5), 4,NG1( 6.5), 2,NG1(6.5) },  /*  26Mb/s */
+	{ 4,NG1(  39), 3,NG1(  26), 4,NG1(19.5), 2,NG1(6.5) },  /*  39Mb/s */
+	{ 4,NG1(  52), 3,NG1(  39), 4,NG1(  26), 2,NG1(6.5) },  /*  52Mb/s */
+	{ 4,NG1(58.5), 3,NG1(  52), 4,NG1(  39), 2,NG1( 13) },  /*58.5Mb/s */
+	{ 4,NG1(  65), 3,NG1(58.5), 4,NG1(  52), 2,NG1( 13) },  /*  65Mb/s */
+
+	/* 2 stream rates */
+
+	{ 3,NG2(  13), 3,NG2(  13), 0,NG2(  13), 0,NG2( 13) },  /*  13Mb/s */
+	{ 4,NG2(  26), 3,NG2(  13), 4,NG2(  13), 0,NG2( 13) },  /*  26Mb/s */
+	{ 4,NG2(  39), 3,NG2(  26), 4,NG2(  13), 2,NG2( 13) },  /*  39Mb/s */
+	{ 4,NG2(  52), 3,NG2(  39), 4,NG2(  26), 2,NG2( 13) },  /*  52Mb/s */
+	{ 4,NG2(  78), 3,NG2(  52), 4,NG2(  39), 2,NG2( 13) },  /*  78Mb/s */
+	{ 4,NG2( 104), 3,NG2(  78), 4,NG2(  52), 2,NG2( 13) },  /* 104Mb/s */
+	{ 4,NG2( 117), 3,NG2( 104), 4,NG2(  78), 2,NG2( 26) },  /* 117Mb/s */
+	{ 4,NG2( 130), 3,NG2( 117), 4,NG2( 104), 2,NG2( 26) },  /* 130Mb/s */
+
+	/* 3 stream rates */
+
+	{ 3,NG3(19.5), 3,NG3(19.5), 0,NG3(19.5), 0,NG3(19.5) },  /*  19Mb/s */
+	{ 3,NG3(  39), 3,NG3(19.5), 0,NG3(19.5), 0,NG3(19.5) },  /*  39Mb/s */
+	{ 3,NG3(58.5), 3,NG3(  39), 0,NG3(19.5), 0,NG3(19.5) },  /*  58Mb/s */
+	{ 3,NG3(  78), 3,NG3(58.5), 0,NG3(  39), 0,NG3(19.5) },  /*  78Mb/s */
+	{ 3,NG3( 117), 3,NG3(  78), 0,NG3(58.5), 0,NG3(19.5) },  /* 117Mb/s */
+	{ 3,NG3( 156), 3,NG3( 117), 0,NG3(  78), 0,NG3(19.5) },  /*  156Mb/s */
+	{ 3,NG3(175.5), 3,NG3( 156), 0,NG3( 117), 0,NG3(  39) },  /*  175Mb/s */
+	{ 3,NG3( 195), 3,NG3( 195), 0,NG3( 156), 0,NG3(58.5) },  /* 195Mb/s */
+
+};
+#undef G
+#undef NG3
+#undef NG2
+#undef NG1
+
+#define H(_r) \
+    (((_r) == 3)   ? 0 : (((_r) == 4.5) ? 1 : (((_r) == 6)  ? 2 : \
+    (((_r) == 9)   ? 3 : (((_r) == 12)  ? 4 : (((_r) == 18) ? 5 : \
+    (((_r) == 24)  ? 6 : (((_r) == 27)  ? 7 : 0))))))))
+static const struct txschedule series_half[] = {
+	{ 3,H( 3), 3,H(  3), 0,H(  3), 0,H( 3) },	/*   3Mb/s */
+	{ 4,H(4.5),3,H(  3), 4,H(  3), 0,H( 3) },	/* 4.5Mb/s */
+	{ 4,H( 6), 3,H(  3), 4,H(  3), 0,H( 3) },	/*   6Mb/s */
+	{ 4,H( 9), 3,H(  6), 4,H(  3), 2,H( 3) },	/*   9Mb/s */
+	{ 4,H(12), 3,H(  9), 4,H(  6), 2,H( 3) },	/*  12Mb/s */
+	{ 4,H(18), 3,H( 12), 4,H(  9), 2,H( 3) },	/*  18Mb/s */
+	{ 4,H(24), 3,H( 18), 4,H( 12), 2,H( 6) },	/*  24Mb/s */
+	{ 4,H(27), 3,H( 24), 4,H( 18), 2,H(12) }	/*  27Mb/s */
+};
+#undef H
+
+#ifdef Q
+#undef Q
+#endif
+#define Q(_r) \
+    (((_r) == 1.5) ? 0 : (((_r) ==2.25) ? 1 : (((_r) == 3)  ? 2 : \
+    (((_r) == 4.5) ? 3 : (((_r) ==  6)  ? 4 : (((_r) == 9)  ? 5 : \
+    (((_r) == 12)  ? 6 : (((_r) == 13.5)? 7 : 0))))))))
+static const struct txschedule series_quarter[] = {
+	{ 3,Q( 1.5),3,Q(1.5), 0,Q(1.5), 0,Q(1.5) },	/* 1.5Mb/s */
+	{ 4,Q(2.25),3,Q(1.5), 4,Q(1.5), 0,Q(1.5) },	/*2.25Mb/s */
+	{ 4,Q(   3),3,Q(1.5), 4,Q(1.5), 0,Q(1.5) },	/*   3Mb/s */
+	{ 4,Q( 4.5),3,Q(  3), 4,Q(1.5), 2,Q(1.5) },	/* 4.5Mb/s */
+	{ 4,Q(   6),3,Q(4.5), 4,Q(  3), 2,Q(1.5) },	/*   6Mb/s */
+	{ 4,Q(   9),3,Q(  6), 4,Q(4.5), 2,Q(1.5) },	/*   9Mb/s */
+	{ 4,Q(  12),3,Q(  9), 4,Q(  6), 2,Q(  3) },	/*  12Mb/s */
+	{ 4,Q(13.5),3,Q( 12), 4,Q(  9), 2,Q(  6) }	/*13.5Mb/s */
+};
+#undef Q
+
+#endif



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201308051522.r75FMoGG021196>