diff options
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); |