PERFORCE change 137686 for review
Sam Leffler
sam at FreeBSD.org
Fri Mar 14 05:24:13 UTC 2008
http://perforce.freebsd.org/chv.cgi?CH=137686
Change 137686 by sam at sam_ebb on 2008/03/14 05:24:04
Major overhaul:
o consolidate various driver-specific hacks by refining
the api's; drivers can accumulate stats on each tx done
or through periodic polling (e.g. ural which collects
stats through cmds) and effect rate selection according
to a sampling interval
o do the initial tx rate selection in ieee80211_amrr_node_init
(probably need to refine for 11b rate sets to start 5.5
instead of 11)
o de-obfuscate some of the code
o eliminate dependence on ni_txrate for tracking the current
rate index since it's now for reporting current tx rate
o handle ni_txrate updates
o automatically add sysctl knobs to net.wlan.X
o fix rate downshifting so it requires "is_enough" frames;
otherwise this can happen if 1 frame is sent successfully
with a retransmit (algorithm is stil utter crap but this
at least eliminates one of the major causes of rapid rate
oscillation)
Affected files ...
.. //depot/projects/vap/sys/net80211/ieee80211_amrr.c#7 edit
.. //depot/projects/vap/sys/net80211/ieee80211_amrr.h#5 edit
Differences ...
==== //depot/projects/vap/sys/net80211/ieee80211_amrr.c#7 (text+ko) ====
@@ -53,68 +53,87 @@
((amn)->amn_retrycnt > (amn)->amn_txcnt / 3)
#define is_enough(amn) \
((amn)->amn_txcnt > 10)
-#define is_min_rate(ni) \
- ((ni)->ni_txrate == 0)
-#define is_max_rate(ni) \
- ((ni)->ni_txrate == (ni)->ni_rates.rs_nrates - 1)
-#define increase_rate(ni) \
- ((ni)->ni_txrate++)
-#define decrease_rate(ni) \
- ((ni)->ni_txrate--)
-#define reset_cnt(amn) \
- do { (amn)->amn_txcnt = (amn)->amn_retrycnt = 0; } while (0)
+
+static void amrr_sysctlattach(struct ieee80211_amrr *amrr,
+ struct sysctl_ctx_list *ctx, struct sysctl_oid *tree);
/* number of references from net80211 layer */
static int nrefs = 0;
void
+ieee80211_amrr_setinterval(struct ieee80211_amrr *amrr, int msecs)
+{
+ int t;
+
+ if (msecs < 100)
+ msecs = 100;
+ t = msecs_to_ticks(msecs);
+ amrr->amrr_interval = (t < 1) ? 1 : t;
+}
+
+void
ieee80211_amrr_init(struct ieee80211_amrr *amrr,
- struct ieee80211vap *vap, int amin, int amax)
+ struct ieee80211vap *vap, int amin, int amax, int interval)
{
/* XXX bounds check? */
amrr->amrr_min_success_threshold = amin;
amrr->amrr_max_success_threshold = amax;
- amrr->amrr_vap = vap;
+ ieee80211_amrr_setinterval(amrr, interval);
+
+ amrr_sysctlattach(amrr, vap->iv_sysctl, vap->iv_oid);
+}
+
+void
+ieee80211_amrr_cleanup(struct ieee80211_amrr *amrr)
+{
}
void
ieee80211_amrr_node_init(struct ieee80211_amrr *amrr,
- struct ieee80211_amrr_node *amn)
+ struct ieee80211_amrr_node *amn, struct ieee80211_node *ni)
{
+ const struct ieee80211_rateset *rs = &ni->ni_rates;
+
+ amn->amn_amrr = amrr;
amn->amn_success = 0;
amn->amn_recovery = 0;
amn->amn_txcnt = amn->amn_retrycnt = 0;
amn->amn_success_threshold = amrr->amrr_min_success_threshold;
+
+ /* pick initial rate */
+ for (amn->amn_rix = rs->rs_nrates - 1;
+ amn->amn_rix > 0 && (rs->rs_rates[amn->amn_rix] & IEEE80211_RATE_VAL) > 72;
+ amn->amn_rix--)
+ ;
+ ni->ni_txrate = rs->rs_rates[amn->amn_rix] & IEEE80211_RATE_VAL;
+ amn->amn_ticks = ticks;
}
-/*
- * Update ni->ni_txrate.
- */
-void
-ieee80211_amrr_choose(struct ieee80211_amrr *amrr, struct ieee80211_node *ni,
- struct ieee80211_amrr_node *amn)
+static int
+amrr_update(struct ieee80211_amrr *amrr, struct ieee80211_amrr_node *amn,
+ struct ieee80211_node *ni)
{
- int need_change = 0;
+ int rix = amn->amn_rix;
+
+ KASSERT(is_enough(amn), ("txcnt %d", amn->amn_txcnt));
- if (is_success(amn) && is_enough(amn)) {
+ if (is_success(amn)) {
amn->amn_success++;
if (amn->amn_success >= amn->amn_success_threshold &&
- !is_max_rate(ni)) {
+ rix + 1 < ni->ni_rates.rs_nrates) {
amn->amn_recovery = 1;
amn->amn_success = 0;
- increase_rate(ni);
- IEEE80211_DPRINTF(amrr->amrr_vap, IEEE80211_MSG_RATECTL,
+ rix++;
+ IEEE80211_DPRINTF(ni->ni_vap, IEEE80211_MSG_RATECTL,
"AMRR increasing rate %d (txcnt=%d retrycnt=%d)\n",
- ni->ni_rates.rs_rates[ni->ni_txrate] &
- IEEE80211_RATE_VAL,
+ ni->ni_rates.rs_rates[rix] & IEEE80211_RATE_VAL,
amn->amn_txcnt, amn->amn_retrycnt);
- need_change = 1;
} else {
amn->amn_recovery = 0;
}
} else if (is_failure(amn)) {
amn->amn_success = 0;
- if (!is_min_rate(ni)) {
+ if (rix > 0) {
if (amn->amn_recovery) {
amn->amn_success_threshold *= 2;
if (amn->amn_success_threshold >
@@ -125,19 +144,76 @@
amn->amn_success_threshold =
amrr->amrr_min_success_threshold;
}
- decrease_rate(ni);
- IEEE80211_DPRINTF(amrr->amrr_vap, IEEE80211_MSG_RATECTL,
+ rix--;
+ IEEE80211_DPRINTF(ni->ni_vap, IEEE80211_MSG_RATECTL,
"AMRR decreasing rate %d (txcnt=%d retrycnt=%d)\n",
- ni->ni_rates.rs_rates[ni->ni_txrate] &
- IEEE80211_RATE_VAL,
+ ni->ni_rates.rs_rates[rix] & IEEE80211_RATE_VAL,
amn->amn_txcnt, amn->amn_retrycnt);
- need_change = 1;
}
amn->amn_recovery = 0;
}
- if (is_enough(amn) || need_change)
- reset_cnt(amn);
+ /* reset counters */
+ amn->amn_txcnt = 0;
+ amn->amn_retrycnt = 0;
+
+ return rix;
+}
+
+/*
+ * Return the rate index to use in sending a data frame.
+ * Update our internal state if it's been long enough.
+ * If the rate changes we also update ni_txrate to match.
+ */
+int
+ieee80211_amrr_choose(struct ieee80211_node *ni,
+ struct ieee80211_amrr_node *amn)
+{
+ struct ieee80211_amrr *amrr = amn->amn_amrr;
+ int rix;
+
+ if (is_enough(amn) && ticks - amn->amn_ticks > amrr->amrr_interval) {
+ rix = amrr_update(amrr, amn, ni);
+ if (rix != amn->amn_rix) {
+ /* update public rate */
+ ni->ni_txrate =
+ ni->ni_rates.rs_rates[rix] & IEEE80211_RATE_VAL;
+ amn->amn_rix = rix;
+ }
+ } else
+ rix = amn->amn_rix;
+ return rix;
+}
+
+static int
+amrr_sysctl_interval(SYSCTL_HANDLER_ARGS)
+{
+ struct ieee80211_amrr *amrr = arg1;
+ int msecs = ticks_to_msecs(amrr->amrr_interval);
+ int error;
+
+ error = sysctl_handle_int(oidp, &msecs, 0, req);
+ if (error || !req->newptr)
+ return error;
+ ieee80211_amrr_setinterval(amrr, msecs);
+ return 0;
+}
+
+static void
+amrr_sysctlattach(struct ieee80211_amrr *amrr,
+ struct sysctl_ctx_list *ctx, struct sysctl_oid *tree)
+{
+
+ SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
+ "amrr_rate_interval", CTLTYPE_INT | CTLFLAG_RW, amrr,
+ 0, amrr_sysctl_interval, "I", "amrr operation interval (ms)");
+ /* XXX bounds check values */
+ SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
+ "amrr_max_sucess_threshold", CTLFLAG_RW,
+ &amrr->amrr_max_success_threshold, 0, "");
+ SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
+ "amrr_min_sucess_threshold", CTLFLAG_RW,
+ &amrr->amrr_min_success_threshold, 0, "");
}
/*
==== //depot/projects/vap/sys/net80211/ieee80211_amrr.h#5 (text+ko) ====
@@ -37,7 +37,7 @@
struct ieee80211_amrr {
u_int amrr_min_success_threshold;
u_int amrr_max_success_threshold;
- struct ieee80211vap *amrr_vap;
+ int amrr_interval; /* update interval (ticks) */
};
#define IEEE80211_AMRR_MIN_SUCCESS_THRESHOLD 1
@@ -47,18 +47,55 @@
* Rate control state for a given node.
*/
struct ieee80211_amrr_node {
+ struct ieee80211_amrr *amn_amrr;/* backpointer */
+ int amn_rix; /* current rate index */
+ int amn_ticks; /* time of last update */
+ /* statistics */
+ u_int amn_txcnt;
u_int amn_success;
+ u_int amn_success_threshold;
u_int amn_recovery;
- u_int amn_success_threshold;
- u_int amn_txcnt;
u_int amn_retrycnt;
};
-void ieee80211_amrr_init(struct ieee80211_amrr *,
- struct ieee80211vap *, int, int);
+void ieee80211_amrr_init(struct ieee80211_amrr *, struct ieee80211vap *,
+ int, int, int);
+void ieee80211_amrr_cleanup(struct ieee80211_amrr *);
+void ieee80211_amrr_setinterval(struct ieee80211_amrr *, int);
void ieee80211_amrr_node_init(struct ieee80211_amrr *,
+ struct ieee80211_amrr_node *, struct ieee80211_node *);
+int ieee80211_amrr_choose(struct ieee80211_node *,
struct ieee80211_amrr_node *);
-void ieee80211_amrr_choose(struct ieee80211_amrr *, struct ieee80211_node *,
- struct ieee80211_amrr_node *);
+
+#define IEEE80211_AMRR_SUCCESS 1
+#define IEEE80211_AMRR_FAILURE 0
+
+/*
+ * Update statistics with tx complete status. Ok is non-zero
+ * if the packet is known to be ACK'd. Retries has the number
+ * retransmissions (i.e. xmit attempts - 1).
+ */
+static __inline void
+ieee80211_amrr_tx_complete(struct ieee80211_amrr_node *amn,
+ int ok, int retries)
+{
+ amn->amn_txcnt++;
+ if (ok)
+ amn->amn_success++;
+ amn->amn_retrycnt += retries;
+}
+/*
+ * Set tx count/retry statistics explicitly. Intended for
+ * drivers that poll the device for statistics maintained
+ * in the device.
+ */
+static __inline void
+ieee80211_amrr_tx_update(struct ieee80211_amrr_node *amn,
+ int txcnt, int success, int retrycnt)
+{
+ amn->amn_txcnt = txcnt;
+ amn->amn_success = success;
+ amn->amn_retrycnt = retrycnt;
+}
#endif /* _NET80211_IEEE80211_AMRR_H_ */
More information about the p4-projects
mailing list