diff options
author | rpaulo <rpaulo@FreeBSD.org> | 2010-04-07 15:29:13 +0000 |
---|---|---|
committer | rpaulo <rpaulo@FreeBSD.org> | 2010-04-07 15:29:13 +0000 |
commit | 69bf804b50328bc699737db57c5d38691d59780a (patch) | |
tree | ea8a3480b8652bfecee1f73168674b2f28571e3b /sys/net80211 | |
parent | 1db184691b1abeac975b128c17b5c4997b7bcf6c (diff) | |
download | FreeBSD-src-69bf804b50328bc699737db57c5d38691d59780a.zip FreeBSD-src-69bf804b50328bc699737db57c5d38691d59780a.tar.gz |
net80211 rate control framework (net80211 ratectl).
This framework allows drivers to abstract the rate control algorithm and
just feed the framework with the usable parameters. The rate control
framework will now deal with passing the parameters to the selected
algorithm. Right now we have AMRR (the default) and RSSADAPT but there's
no way to select one with ifconfig, yet.
The objective is to have more rate control algorithms in the net80211
stack so all drivers[0] can use it. Ideally, we'll have the well-known
sample rate control algorithm in the net80211 at some point so all
drivers can use it (not just ath).
[0] all drivers that do rate control in software, that is.
Reviewed by: bschmidt, thompsa, weyongo
MFC after: 1 months
Diffstat (limited to 'sys/net80211')
-rw-r--r-- | sys/net80211/ieee80211.c | 3 | ||||
-rw-r--r-- | sys/net80211/ieee80211_amrr.c | 142 | ||||
-rw-r--r-- | sys/net80211/ieee80211_amrr.h | 40 | ||||
-rw-r--r-- | sys/net80211/ieee80211_freebsd.h | 13 | ||||
-rw-r--r-- | sys/net80211/ieee80211_node.c | 2 | ||||
-rw-r--r-- | sys/net80211/ieee80211_node.h | 3 | ||||
-rw-r--r-- | sys/net80211/ieee80211_ratectl.c | 66 | ||||
-rw-r--r-- | sys/net80211/ieee80211_ratectl.h | 127 | ||||
-rw-r--r-- | sys/net80211/ieee80211_rssadapt.c | 128 | ||||
-rw-r--r-- | sys/net80211/ieee80211_rssadapt.h | 32 | ||||
-rw-r--r-- | sys/net80211/ieee80211_var.h | 5 |
11 files changed, 423 insertions, 138 deletions
diff --git a/sys/net80211/ieee80211.c b/sys/net80211/ieee80211.c index 8a50bc0..3d5669c 100644 --- a/sys/net80211/ieee80211.c +++ b/sys/net80211/ieee80211.c @@ -49,6 +49,7 @@ __FBSDID("$FreeBSD$"); #ifdef IEEE80211_SUPPORT_SUPERG #include <net80211/ieee80211_superg.h> #endif +#include <net80211/ieee80211_ratectl.h> #include <net/bpf.h> @@ -486,6 +487,8 @@ ieee80211_vap_setup(struct ieee80211com *ic, struct ieee80211vap *vap, ieee80211_regdomain_vattach(vap); ieee80211_radiotap_vattach(vap); + ieee80211_ratectl_set(vap, IEEE80211_RATECTL_AMRR); + return 0; } diff --git a/sys/net80211/ieee80211_amrr.c b/sys/net80211/ieee80211_amrr.c index a759e64..e8eed09 100644 --- a/sys/net80211/ieee80211_amrr.c +++ b/sys/net80211/ieee80211_amrr.c @@ -1,6 +1,7 @@ /* $OpenBSD: ieee80211_amrr.c,v 1.1 2006/06/17 19:07:19 damien Exp $ */ /*- + * Copyright (c) 2010 Rui Paulo <rpaulo@FreeBSD.org> * Copyright (c) 2006 * Damien Bergamini <damien.bergamini@free.fr> * @@ -46,6 +47,7 @@ __FBSDID("$FreeBSD$"); #include <net80211/ieee80211_var.h> #include <net80211/ieee80211_amrr.h> +#include <net80211/ieee80211_ratectl.h> #define is_success(amn) \ ((amn)->amn_retrycnt < (amn)->amn_txcnt / 10) @@ -54,15 +56,45 @@ __FBSDID("$FreeBSD$"); #define is_enough(amn) \ ((amn)->amn_txcnt > 10) -static void amrr_sysctlattach(struct ieee80211_amrr *amrr, - struct sysctl_ctx_list *ctx, struct sysctl_oid *tree); +static void amrr_setinterval(const struct ieee80211vap *, int); +static void amrr_init(struct ieee80211vap *); +static void amrr_deinit(struct ieee80211vap *); +static void amrr_node_init(struct ieee80211_node *); +static void amrr_node_deinit(struct ieee80211_node *); +static int amrr_update(struct ieee80211_amrr *, + struct ieee80211_amrr_node *, struct ieee80211_node *); +static int amrr_rate(struct ieee80211_node *, void *, uint32_t); +static void amrr_tx_complete(const struct ieee80211vap *, + const struct ieee80211_node *, int, + void *, void *); +static void amrr_tx_update(const struct ieee80211vap *vap, + const struct ieee80211_node *, void *, void *, void *); +static void amrr_sysctlattach(struct ieee80211vap *, + struct sysctl_ctx_list *, struct sysctl_oid *); /* number of references from net80211 layer */ static int nrefs = 0; -void -ieee80211_amrr_setinterval(struct ieee80211_amrr *amrr, int msecs) +static const struct ieee80211_ratectl amrr = { + .ir_name = "amrr", + .ir_attach = NULL, + .ir_detach = NULL, + .ir_init = amrr_init, + .ir_deinit = amrr_deinit, + .ir_node_init = amrr_node_init, + .ir_node_deinit = amrr_node_deinit, + .ir_rate = amrr_rate, + .ir_tx_complete = amrr_tx_complete, + .ir_tx_update = amrr_tx_update, + .ir_setinterval = amrr_setinterval, +}; +IEEE80211_RATECTL_MODULE(amrr, 1); +IEEE80211_RATECTL_ALG(amrr, IEEE80211_RATECTL_AMRR, amrr); + +static void +amrr_setinterval(const struct ieee80211vap *vap, int msecs) { + struct ieee80211_amrr *amrr = vap->iv_rs; int t; if (msecs < 100) @@ -71,29 +103,42 @@ ieee80211_amrr_setinterval(struct ieee80211_amrr *amrr, int msecs) amrr->amrr_interval = (t < 1) ? 1 : t; } -void -ieee80211_amrr_init(struct ieee80211_amrr *amrr, - struct ieee80211vap *vap, int amin, int amax, int interval) +static void +amrr_init(struct ieee80211vap *vap) { - /* XXX bounds check? */ - amrr->amrr_min_success_threshold = amin; - amrr->amrr_max_success_threshold = amax; - ieee80211_amrr_setinterval(amrr, interval); + struct ieee80211_amrr *amrr; + + KASSERT(vap->iv_rs == NULL, ("%s called multiple times", __func__)); - amrr_sysctlattach(amrr, vap->iv_sysctl, vap->iv_oid); + vap->iv_rs = malloc(sizeof(struct ieee80211_amrr), M_80211_RATECTL, + M_WAITOK|M_ZERO); + amrr = vap->iv_rs; + amrr->amrr_min_success_threshold = IEEE80211_AMRR_MIN_SUCCESS_THRESHOLD; + amrr->amrr_max_success_threshold = IEEE80211_AMRR_MAX_SUCCESS_THRESHOLD; + amrr_setinterval(vap, 500 /* ms */); + amrr_sysctlattach(vap, vap->iv_sysctl, vap->iv_oid); } -void -ieee80211_amrr_cleanup(struct ieee80211_amrr *amrr) +static void +amrr_deinit(struct ieee80211vap *vap) { + free(vap->iv_rs, M_80211_RATECTL); } -void -ieee80211_amrr_node_init(struct ieee80211_amrr *amrr, - struct ieee80211_amrr_node *amn, struct ieee80211_node *ni) +static void +amrr_node_init(struct ieee80211_node *ni) { const struct ieee80211_rateset *rs = &ni->ni_rates; + struct ieee80211vap *vap = ni->ni_vap; + struct ieee80211_amrr *amrr = vap->iv_rs; + struct ieee80211_amrr_node *amn; + KASSERT(ni->ni_rctls == NULL, ("%s: ni_rctls already initialized", + __func__)); + + ni->ni_rctls = malloc(sizeof(struct ieee80211_amrr_node), + M_80211_RATECTL, M_WAITOK|M_ZERO); + amn = ni->ni_rctls; amn->amn_amrr = amrr; amn->amn_success = 0; amn->amn_recovery = 0; @@ -112,6 +157,12 @@ ieee80211_amrr_node_init(struct ieee80211_amrr *amrr, "AMRR initial rate %d", ni->ni_txrate); } +static void +amrr_node_deinit(struct ieee80211_node *ni) +{ + free(ni->ni_rctls, M_80211_RATECTL); +} + static int amrr_update(struct ieee80211_amrr *amrr, struct ieee80211_amrr_node *amn, struct ieee80211_node *ni) @@ -168,10 +219,10 @@ amrr_update(struct ieee80211_amrr *amrr, struct ieee80211_amrr_node *amn, * 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) +static int +amrr_rate(struct ieee80211_node *ni, void *arg __unused, uint32_t iarg __unused) { + struct ieee80211_amrr_node *amn = ni->ni_rctls; struct ieee80211_amrr *amrr = amn->amn_amrr; int rix; @@ -189,27 +240,65 @@ ieee80211_amrr_choose(struct ieee80211_node *ni, return rix; } +/* + * 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 void +amrr_tx_complete(const struct ieee80211vap *vap, + const struct ieee80211_node *ni, int ok, + void *arg1, void *arg2 __unused) +{ + struct ieee80211_amrr_node *amn = ni->ni_rctls; + int retries = *(int *)arg1; + + 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 void +amrr_tx_update(const struct ieee80211vap *vap, const struct ieee80211_node *ni, + void *arg1, void *arg2, void *arg3) +{ + struct ieee80211_amrr_node *amn = ni->ni_rctls; + int txcnt = *(int *)arg1, success = *(int *)arg2, retrycnt = *(int *)arg3; + + amn->amn_txcnt = txcnt; + amn->amn_success = success; + amn->amn_retrycnt = retrycnt; +} + static int amrr_sysctl_interval(SYSCTL_HANDLER_ARGS) { - struct ieee80211_amrr *amrr = arg1; + struct ieee80211vap *vap = arg1; + struct ieee80211_amrr *amrr = vap->iv_rs; 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); + amrr_setinterval(vap, msecs); return 0; } static void -amrr_sysctlattach(struct ieee80211_amrr *amrr, +amrr_sysctlattach(struct ieee80211vap *vap, struct sysctl_ctx_list *ctx, struct sysctl_oid *tree) { + struct ieee80211_amrr *amrr = vap->iv_rs; SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, - "amrr_rate_interval", CTLTYPE_INT | CTLFLAG_RW, amrr, + "amrr_rate_interval", CTLTYPE_INT | CTLFLAG_RW, vap, 0, amrr_sysctl_interval, "I", "amrr operation interval (ms)"); /* XXX bounds check values */ SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, @@ -219,8 +308,3 @@ amrr_sysctlattach(struct ieee80211_amrr *amrr, "amrr_min_sucess_threshold", CTLFLAG_RW, &amrr->amrr_min_success_threshold, 0, ""); } - -/* - * Module glue. - */ -IEEE80211_RATE_MODULE(amrr, 1); diff --git a/sys/net80211/ieee80211_amrr.h b/sys/net80211/ieee80211_amrr.h index c03f699..ec67bdf 100644 --- a/sys/net80211/ieee80211_amrr.h +++ b/sys/net80211/ieee80211_amrr.h @@ -58,44 +58,4 @@ struct ieee80211_amrr_node { u_int amn_retrycnt; }; -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 *); - -#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_ */ diff --git a/sys/net80211/ieee80211_freebsd.h b/sys/net80211/ieee80211_freebsd.h index 6a8875a..861ac51 100644 --- a/sys/net80211/ieee80211_freebsd.h +++ b/sys/net80211/ieee80211_freebsd.h @@ -386,14 +386,19 @@ TEXT_SET(auth_set, name##_modevent) /* * Rate control modules provide tx rate control support. */ -#define IEEE80211_RATE_MODULE(alg, version) \ -_IEEE80211_POLICY_MODULE(rate, alg, version); \ +#define IEEE80211_RATECTL_MODULE(alg, version) \ + _IEEE80211_POLICY_MODULE(ratectl, alg, version); \ + +#define IEEE80211_RATECTL_ALG(name, alg, v) \ static void \ alg##_modevent(int type) \ { \ - /* XXX nothing to do until the rate control framework arrives */\ + if (type == MOD_LOAD) \ + ieee80211_ratectl_register(alg, &v); \ + else \ + ieee80211_ratectl_unregister(alg); \ } \ -TEXT_SET(rate##_set, alg##_modevent) +TEXT_SET(ratectl##_set, alg##_modevent) struct ieee80211req; typedef int ieee80211_ioctl_getfunc(struct ieee80211vap *, diff --git a/sys/net80211/ieee80211_node.c b/sys/net80211/ieee80211_node.c index bccb6d5..b17f42f 100644 --- a/sys/net80211/ieee80211_node.c +++ b/sys/net80211/ieee80211_node.c @@ -51,6 +51,7 @@ __FBSDID("$FreeBSD$"); #endif #include <net80211/ieee80211_wds.h> #include <net80211/ieee80211_mesh.h> +#include <net80211/ieee80211_ratectl.h> #include <net/bpf.h> @@ -1035,6 +1036,7 @@ node_free(struct ieee80211_node *ni) { struct ieee80211com *ic = ni->ni_ic; + ieee80211_ratectl_node_deinit(ni); ic->ic_node_cleanup(ni); ieee80211_ies_cleanup(&ni->ni_ies); ieee80211_psq_cleanup(&ni->ni_psq); diff --git a/sys/net80211/ieee80211_node.h b/sys/net80211/ieee80211_node.h index 63b2355..01bb2cf 100644 --- a/sys/net80211/ieee80211_node.h +++ b/sys/net80211/ieee80211_node.h @@ -218,7 +218,8 @@ struct ieee80211_node { struct ieee80211_nodestats ni_stats; /* per-node statistics */ struct ieee80211vap *ni_wdsvap; /* associated WDS vap */ - uint64_t ni_spare[4]; + void *ni_rctls; /* private ratectl state */ + uint64_t ni_spare[3]; }; MALLOC_DECLARE(M_80211_NODE); MALLOC_DECLARE(M_80211_NODE_IE); diff --git a/sys/net80211/ieee80211_ratectl.c b/sys/net80211/ieee80211_ratectl.c new file mode 100644 index 0000000..2e8eb7e --- /dev/null +++ b/sys/net80211/ieee80211_ratectl.c @@ -0,0 +1,66 @@ +/*- + * Copyright (c) 2010 Rui Paulo <rpaulo@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. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, 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 DAMAGE. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/socket.h> + +#include <net/if.h> +#include <net/if_media.h> + +#include <net80211/ieee80211_var.h> +#include <net80211/ieee80211_ratectl.h> + +static const struct ieee80211_ratectl *ratectls[IEEE80211_RATECTL_MAX]; + +MALLOC_DEFINE(M_80211_RATECTL, "80211ratectl", "802.11 rate control"); + +void +ieee80211_ratectl_register(int type, const struct ieee80211_ratectl *ratectl) +{ + if (type >= IEEE80211_RATECTL_MAX) + return; + ratectls[type] = ratectl; +} + +void +ieee80211_ratectl_unregister(int type) +{ + if (type >= IEEE80211_RATECTL_MAX) + return; + ratectls[type] = NULL; +} + +void +ieee80211_ratectl_set(struct ieee80211vap *vap, int type) +{ + if (type >= IEEE80211_RATECTL_MAX) + return; + vap->iv_rate = ratectls[type]; +} diff --git a/sys/net80211/ieee80211_ratectl.h b/sys/net80211/ieee80211_ratectl.h new file mode 100644 index 0000000..1093df4 --- /dev/null +++ b/sys/net80211/ieee80211_ratectl.h @@ -0,0 +1,127 @@ +/*- + * Copyright (c) 2010 Rui Paulo <rpaulo@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. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, 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 DAMAGE. + * + * $FreeBSD$ + */ + +enum ieee80211_ratealgs { + IEEE80211_RATECTL_AMRR = 0, + IEEE80211_RATECTL_RSSADAPT = 1, + IEEE80211_RATECTL_ONOE = 2, + IEEE80211_RATECTL_SAMPLE = 3, + IEEE80211_RATECTL_MAX +}; + +#define IEEE80211_RATECTL_TX_SUCCESS 0 +#define IEEE80211_RATECTL_TX_FAILURE 1 + +struct ieee80211_ratectl { + const char *ir_name; + int (*ir_attach)(const struct ieee80211vap *); + void (*ir_detach)(const struct ieee80211vap *); + void (*ir_init)(struct ieee80211vap *); + void (*ir_deinit)(struct ieee80211vap *); + void (*ir_node_init)(struct ieee80211_node *); + void (*ir_node_deinit)(struct ieee80211_node *); + int (*ir_rate)(struct ieee80211_node *, void *, uint32_t); + void (*ir_tx_complete)(const struct ieee80211vap *, + const struct ieee80211_node *, int, + void *, void *); + void (*ir_tx_update)(const struct ieee80211vap *, + const struct ieee80211_node *, + void *, void *, void *); + void (*ir_setinterval)(const struct ieee80211vap *, int); +}; + +void ieee80211_ratectl_register(int, const struct ieee80211_ratectl *); +void ieee80211_ratectl_unregister(int); +void ieee80211_ratectl_set(struct ieee80211vap *, int); + +MALLOC_DECLARE(M_80211_RATECTL); + +static void __inline +ieee80211_ratectl_init(struct ieee80211vap *vap) +{ + vap->iv_rate->ir_init(vap); +} + +static void __inline +ieee80211_ratectl_deinit(struct ieee80211vap *vap) +{ + vap->iv_rate->ir_deinit(vap); +} + +static void __inline +ieee80211_ratectl_node_init(struct ieee80211_node *ni) +{ + const struct ieee80211vap *vap = ni->ni_vap; + + vap->iv_rate->ir_node_init(ni); +} + +static void __inline +ieee80211_ratectl_node_deinit(struct ieee80211_node *ni) +{ + const struct ieee80211vap *vap = ni->ni_vap; + + vap->iv_rate->ir_node_deinit(ni); +} + +static int __inline +ieee80211_ratectl_rate(struct ieee80211_node *ni, void *arg, uint32_t iarg) +{ + const struct ieee80211vap *vap = ni->ni_vap; + + if (ni->ni_rctls == NULL) /* ratectl not setup */ + return; + return vap->iv_rate->ir_rate(ni, arg, iarg); +} + +static void __inline +ieee80211_ratectl_tx_complete(const struct ieee80211vap *vap, + const struct ieee80211_node *ni, int status, void *arg1, void *arg2) +{ + if (ni->ni_rctls == NULL) /* ratectl not setup */ + return; + vap->iv_rate->ir_tx_complete(vap, ni, status, arg1, arg2); +} + +static void __inline +ieee80211_ratectl_tx_update(const struct ieee80211vap *vap, + const struct ieee80211_node *ni, void *arg1, void *arg2, void *arg3) +{ + if (vap->iv_rate->ir_tx_update == NULL) + return; + if (ni->ni_rctls == NULL) /* ratectl not setup */ + return; + vap->iv_rate->ir_tx_update(vap, ni, arg1, arg2, arg3); +} + +static void __inline +ieee80211_ratectl_setinterval(const struct ieee80211vap *vap, int msecs) +{ + if (vap->iv_rate->ir_setinterval == NULL) + return; + vap->iv_rate->ir_setinterval(vap, msecs); +} diff --git a/sys/net80211/ieee80211_rssadapt.c b/sys/net80211/ieee80211_rssadapt.c index f1fc409..e90ad57 100644 --- a/sys/net80211/ieee80211_rssadapt.c +++ b/sys/net80211/ieee80211_rssadapt.c @@ -1,6 +1,7 @@ /* $FreeBSD$ */ /* $NetBSD: ieee80211_rssadapt.c,v 1.9 2005/02/26 22:45:09 perry Exp $ */ /*- + * Copyright (c) 2010 Rui Paulo <rpaulo@FreeBSD.org> * Copyright (c) 2003, 2004 David Young. All rights reserved. * * Redistribution and use in source and binary forms, with or @@ -42,6 +43,7 @@ #include <net80211/ieee80211_var.h> #include <net80211/ieee80211_rssadapt.h> +#include <net80211/ieee80211_ratectl.h> struct rssadapt_expavgctl { /* RSS threshold decay. */ @@ -71,15 +73,45 @@ static struct rssadapt_expavgctl master_expavgctl = { (parm##_denom - parm##_old) * (new)) / \ parm##_denom) -static void rssadapt_sysctlattach(struct ieee80211_rssadapt *rs, - struct sysctl_ctx_list *ctx, struct sysctl_oid *tree); +static void rssadapt_setinterval(const struct ieee80211vap *, int); +static void rssadapt_init(struct ieee80211vap *); +static void rssadapt_deinit(struct ieee80211vap *); +static void rssadapt_updatestats(struct ieee80211_rssadapt_node *); +static void rssadapt_node_init(struct ieee80211_node *); +static void rssadapt_node_deinit(struct ieee80211_node *); +static int rssadapt_rate(struct ieee80211_node *, void *, uint32_t); +static void rssadapt_lower_rate(struct ieee80211_rssadapt_node *, int, int); +static void rssadapt_raise_rate(struct ieee80211_rssadapt_node *, + int, int); +static void rssadapt_tx_complete(const struct ieee80211vap *, + const struct ieee80211_node *, int, + void *, void *); +static void rssadapt_sysctlattach(struct ieee80211vap *, + struct sysctl_ctx_list *, struct sysctl_oid *); /* number of references from net80211 layer */ static int nrefs = 0; -void -ieee80211_rssadapt_setinterval(struct ieee80211_rssadapt *rs, int msecs) +static const struct ieee80211_ratectl rssadapt = { + .ir_name = "rssadapt", + .ir_attach = NULL, + .ir_detach = NULL, + .ir_init = rssadapt_init, + .ir_deinit = rssadapt_deinit, + .ir_node_init = rssadapt_node_init, + .ir_node_deinit = rssadapt_node_deinit, + .ir_rate = rssadapt_rate, + .ir_tx_complete = rssadapt_tx_complete, + .ir_tx_update = NULL, + .ir_setinterval = rssadapt_setinterval, +}; +IEEE80211_RATECTL_MODULE(rssadapt, 1); +IEEE80211_RATECTL_ALG(rssadapt, IEEE80211_RATECTL_RSSADAPT, rssadapt); + +static void +rssadapt_setinterval(const struct ieee80211vap *vap, int msecs) { + struct ieee80211_rssadapt *rs = vap->iv_rs; int t; if (msecs < 100) @@ -88,18 +120,26 @@ ieee80211_rssadapt_setinterval(struct ieee80211_rssadapt *rs, int msecs) rs->interval = (t < 1) ? 1 : t; } -void -ieee80211_rssadapt_init(struct ieee80211_rssadapt *rs, struct ieee80211vap *vap, int interval) +static void +rssadapt_init(struct ieee80211vap *vap) { + struct ieee80211_rssadapt *rs; + + KASSERT(vap->iv_rs == NULL, ("%s: iv_rs already initialized", + __func__)); + + rs = malloc(sizeof(struct ieee80211_rssadapt), M_80211_RATECTL, + M_WAITOK|M_ZERO); + vap->iv_rs = rs; rs->vap = vap; - ieee80211_rssadapt_setinterval(rs, interval); - - rssadapt_sysctlattach(rs, vap->iv_sysctl, vap->iv_oid); + rssadapt_setinterval(vap, 500 /* msecs */); + rssadapt_sysctlattach(vap, vap->iv_sysctl, vap->iv_oid); } -void -ieee80211_rssadapt_cleanup(struct ieee80211_rssadapt *rs) +static void +rssadapt_deinit(struct ieee80211vap *vap) { + free(vap->iv_rs, M_80211_RATECTL); } static void @@ -118,12 +158,16 @@ rssadapt_updatestats(struct ieee80211_rssadapt_node *ra) ra->ra_raise_interval = msecs_to_ticks(interval); } -void -ieee80211_rssadapt_node_init(struct ieee80211_rssadapt *rsa, - struct ieee80211_rssadapt_node *ra, struct ieee80211_node *ni) +static void +rssadapt_node_init(struct ieee80211_node *ni) { + struct ieee80211_rssadapt_node *ra; + struct ieee80211_rssadapt *rsa = ni->ni_vap->iv_rs; const struct ieee80211_rateset *rs = &ni->ni_rates; + ra = malloc(sizeof(struct ieee80211_rssadapt_node), M_80211_RATECTL, + M_WAITOK|M_ZERO); + ni->ni_rctls = ra; ra->ra_rs = rsa; ra->ra_rates = *rs; rssadapt_updatestats(ra); @@ -140,6 +184,13 @@ ieee80211_rssadapt_node_init(struct ieee80211_rssadapt *rsa, "RSSADAPT initial rate %d", ni->ni_txrate); } +static void +rssadapt_node_deinit(struct ieee80211_node *ni) +{ + + free(ni->ni_rctls, M_80211_RATECTL); +} + static __inline int bucket(int pktlen) { @@ -155,10 +206,11 @@ bucket(int pktlen) return thridx; } -int -ieee80211_rssadapt_choose(struct ieee80211_node *ni, - struct ieee80211_rssadapt_node *ra, u_int pktlen) +static int +rssadapt_rate(struct ieee80211_node *ni, void *arg __unused, uint32_t iarg) { + struct ieee80211_rssadapt_node *ra = ni->ni_rctls; + u_int pktlen = iarg; const struct ieee80211_rateset *rs = &ra->ra_rates; uint16_t (*thrs)[IEEE80211_RATE_SIZE]; int rix, rssi; @@ -193,9 +245,8 @@ ieee80211_rssadapt_choose(struct ieee80211_node *ni, * raise the RSS threshold for transmitting packets of similar length at * the same data rate. */ -void -ieee80211_rssadapt_lower_rate(struct ieee80211_rssadapt_node *ra, - int pktlen, int rssi) +static void +rssadapt_lower_rate(struct ieee80211_rssadapt_node *ra, int pktlen, int rssi) { uint16_t last_thr; uint16_t (*thrs)[IEEE80211_RATE_SIZE]; @@ -214,9 +265,8 @@ ieee80211_rssadapt_lower_rate(struct ieee80211_rssadapt_node *ra, last_thr, (*thrs)[rix], rssi); } -void -ieee80211_rssadapt_raise_rate(struct ieee80211_rssadapt_node *ra, - int pktlen, int rssi) +static void +rssadapt_raise_rate(struct ieee80211_rssadapt_node *ra, int pktlen, int rssi) { uint16_t (*thrs)[IEEE80211_RATE_SIZE]; uint16_t newthr, oldthr; @@ -243,31 +293,45 @@ ieee80211_rssadapt_raise_rate(struct ieee80211_rssadapt_node *ra, } } +static void +rssadapt_tx_complete(const struct ieee80211vap *vap, + const struct ieee80211_node *ni, int success, void *arg1, void *arg2) +{ + struct ieee80211_rssadapt_node *ra = ni->ni_rctls; + int pktlen = *(int *)arg1, rssi = *(int *)arg2; + + if (success) { + ra->ra_nok++; + if ((ra->ra_rix + 1) < ra->ra_rates.rs_nrates && + (ticks - ra->ra_last_raise) >= ra->ra_raise_interval) + rssadapt_raise_rate(ra, pktlen, rssi); + } else { + ra->ra_nfail++; + rssadapt_lower_rate(ra, pktlen, rssi); + } +} + static int rssadapt_sysctl_interval(SYSCTL_HANDLER_ARGS) { - struct ieee80211_rssadapt *rs = arg1; + struct ieee80211vap *vap = arg1; + struct ieee80211_rssadapt *rs = vap->iv_rs; int msecs = ticks_to_msecs(rs->interval); int error; error = sysctl_handle_int(oidp, &msecs, 0, req); if (error || !req->newptr) return error; - ieee80211_rssadapt_setinterval(rs, msecs); + rssadapt_setinterval(vap, msecs); return 0; } static void -rssadapt_sysctlattach(struct ieee80211_rssadapt *rs, +rssadapt_sysctlattach(struct ieee80211vap *vap, struct sysctl_ctx_list *ctx, struct sysctl_oid *tree) { SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, - "rssadapt_rate_interval", CTLTYPE_INT | CTLFLAG_RW, rs, + "rssadapt_rate_interval", CTLTYPE_INT | CTLFLAG_RW, vap, 0, rssadapt_sysctl_interval, "I", "rssadapt operation interval (ms)"); } - -/* - * Module glue. - */ -IEEE80211_RATE_MODULE(rssadapt, 1); diff --git a/sys/net80211/ieee80211_rssadapt.h b/sys/net80211/ieee80211_rssadapt.h index b454f43..ee1d2d9 100644 --- a/sys/net80211/ieee80211_rssadapt.h +++ b/sys/net80211/ieee80211_rssadapt.h @@ -43,7 +43,7 @@ #define IEEE80211_RSSADAPT_BKTPOWER 3 /* 2**_BKTPOWER */ struct ieee80211_rssadapt { - struct ieee80211vap *vap; + const struct ieee80211vap *vap; int interval; /* update interval (ticks) */ }; @@ -66,36 +66,6 @@ struct ieee80211_rssadapt_node { [IEEE80211_RATE_SIZE]; }; -void ieee80211_rssadapt_init(struct ieee80211_rssadapt *, - struct ieee80211vap *, int); -void ieee80211_rssadapt_cleanup(struct ieee80211_rssadapt *); -void ieee80211_rssadapt_setinterval(struct ieee80211_rssadapt *, int); -void ieee80211_rssadapt_node_init(struct ieee80211_rssadapt *, - struct ieee80211_rssadapt_node *, struct ieee80211_node *); -int ieee80211_rssadapt_choose(struct ieee80211_node *, - struct ieee80211_rssadapt_node *, u_int); - -/* NB: these are public only for the inline below */ -void ieee80211_rssadapt_raise_rate(struct ieee80211_rssadapt_node *, - int pktlen, int rssi); -void ieee80211_rssadapt_lower_rate(struct ieee80211_rssadapt_node *, - int pktlen, int rssi); - #define IEEE80211_RSSADAPT_SUCCESS 1 #define IEEE80211_RSSADAPT_FAILURE 0 - -static __inline void -ieee80211_rssadapt_tx_complete(struct ieee80211_rssadapt_node *ra, - int success, int pktlen, int rssi) -{ - if (success) { - ra->ra_nok++; - if ((ra->ra_rix + 1) < ra->ra_rates.rs_nrates && - (ticks - ra->ra_last_raise) >= ra->ra_raise_interval) - ieee80211_rssadapt_raise_rate(ra, pktlen, rssi); - } else { - ra->ra_nfail++; - ieee80211_rssadapt_lower_rate(ra, pktlen, rssi); - } -} #endif /* _NET80211_IEEE80211_RSSADAPT_H_ */ diff --git a/sys/net80211/ieee80211_var.h b/sys/net80211/ieee80211_var.h index 3fa0aec..ff3694f 100644 --- a/sys/net80211/ieee80211_var.h +++ b/sys/net80211/ieee80211_var.h @@ -436,6 +436,9 @@ struct ieee80211vap { const struct ieee80211_aclator *iv_acl; /* acl glue */ void *iv_as; /* private aclator state */ + const struct ieee80211_ratectl *iv_rate; + void *iv_rs; /* private ratectl state */ + struct ieee80211_tdma_state *iv_tdma; /* tdma state */ struct ieee80211_mesh_state *iv_mesh; /* MBSS state */ struct ieee80211_hwmp_state *iv_hwmp; /* HWMP state */ @@ -471,7 +474,7 @@ struct ieee80211vap { /* 802.3 output method for raw frame xmit */ int (*iv_output)(struct ifnet *, struct mbuf *, struct sockaddr *, struct route *); - uint64_t iv_spare[8]; + uint64_t iv_spare[6]; }; MALLOC_DECLARE(M_80211_VAP); |