summaryrefslogtreecommitdiffstats
path: root/sys/net80211
diff options
context:
space:
mode:
Diffstat (limited to 'sys/net80211')
-rw-r--r--sys/net80211/ieee80211.c3
-rw-r--r--sys/net80211/ieee80211_amrr.c142
-rw-r--r--sys/net80211/ieee80211_amrr.h40
-rw-r--r--sys/net80211/ieee80211_freebsd.h13
-rw-r--r--sys/net80211/ieee80211_node.c2
-rw-r--r--sys/net80211/ieee80211_node.h3
-rw-r--r--sys/net80211/ieee80211_ratectl.c66
-rw-r--r--sys/net80211/ieee80211_ratectl.h127
-rw-r--r--sys/net80211/ieee80211_rssadapt.c128
-rw-r--r--sys/net80211/ieee80211_rssadapt.h32
-rw-r--r--sys/net80211/ieee80211_var.h5
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);
OpenPOWER on IntegriCloud