summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien Bergamini <damien@cvs.openbsd.org>2006-06-17 19:07:20 +0000
committerDamien Bergamini <damien@cvs.openbsd.org>2006-06-17 19:07:20 +0000
commit450bd603f12aa3967b92c42500ad81f481d392f0 (patch)
treeb5858fbb9926989a29a6f8fc9ece501364d78ced
parent0687c41ffcf408ac7d8bdbf417add41082bfc17e (diff)
Move AMRR rate control algorithm out of wpi(4) and ural(4), into net80211.
ok brad@
-rw-r--r--sys/conf/files3
-rw-r--r--sys/dev/pci/if_wpi.c175
-rw-r--r--sys/dev/pci/if_wpireg.h4
-rw-r--r--sys/dev/pci/if_wpivar.h13
-rw-r--r--sys/dev/usb/if_ral.c97
-rw-r--r--sys/dev/usb/if_ralvar.h85
-rw-r--r--sys/net80211/ieee80211_amrr.c115
-rw-r--r--sys/net80211/ieee80211_amrr.h54
8 files changed, 276 insertions, 270 deletions
diff --git a/sys/conf/files b/sys/conf/files
index 078e613cb8c..2012f96135d 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -1,4 +1,4 @@
-# $OpenBSD: files,v 1.376 2006/06/02 20:25:09 pedro Exp $
+# $OpenBSD: files,v 1.377 2006/06/17 19:07:19 damien Exp $
# $NetBSD: files,v 1.87 1996/05/19 17:17:50 jonathan Exp $
# @(#)files.newconf 7.5 (Berkeley) 5/10/93
@@ -742,6 +742,7 @@ file net/if_enc.c enc needs-count
file net/if_gre.c gre needs-count
file net/if_trunk.c trunk needs-count
file net80211/ieee80211.c wlan
+file net80211/ieee80211_amrr.c wlan
file net80211/ieee80211_crypto.c wlan
file net80211/ieee80211_input.c wlan
file net80211/ieee80211_ioctl.c wlan
diff --git a/sys/dev/pci/if_wpi.c b/sys/dev/pci/if_wpi.c
index 998ecf8553d..7772e78f522 100644
--- a/sys/dev/pci/if_wpi.c
+++ b/sys/dev/pci/if_wpi.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_wpi.c,v 1.20 2006/06/17 18:35:46 damien Exp $ */
+/* $OpenBSD: if_wpi.c,v 1.21 2006/06/17 19:07:19 damien Exp $ */
/*-
* Copyright (c) 2006
@@ -58,6 +58,7 @@
#include <netinet/ip.h>
#include <net80211/ieee80211_var.h>
+#include <net80211/ieee80211_amrr.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/pci/if_wpireg.h>
@@ -103,8 +104,6 @@ int wpi_alloc_tx_ring(struct wpi_softc *, struct wpi_tx_ring *,
void wpi_reset_tx_ring(struct wpi_softc *, struct wpi_tx_ring *);
void wpi_free_tx_ring(struct wpi_softc *, struct wpi_tx_ring *);
struct ieee80211_node *wpi_node_alloc(struct ieee80211com *);
-void wpi_node_copy(struct ieee80211com *, struct ieee80211_node *,
- const struct ieee80211_node *);
int wpi_media_change(struct ifnet *);
int wpi_newstate(struct ieee80211com *, enum ieee80211_state, int);
void wpi_mem_lock(struct wpi_softc *);
@@ -121,8 +120,7 @@ int wpi_load_firmware(struct wpi_softc *, uint32_t, const char *,
int);
void wpi_rx_intr(struct wpi_softc *, struct wpi_rx_desc *,
struct wpi_rx_data *);
-void wpi_tx_intr(struct wpi_softc *, struct wpi_rx_desc *,
- struct wpi_rx_data *);
+void wpi_tx_intr(struct wpi_softc *, struct wpi_rx_desc *);
void wpi_cmd_intr(struct wpi_softc *, struct wpi_rx_desc *);
void wpi_notif_intr(struct wpi_softc *);
int wpi_intr(void *);
@@ -147,11 +145,10 @@ int wpi_reset(struct wpi_softc *);
void wpi_hw_config(struct wpi_softc *);
int wpi_init(struct ifnet *);
void wpi_stop(struct ifnet *, int);
-
-/* rate control algorithm: should be moved to net80211 */
-void wpi_amrr_init(struct wpi_amrr *);
+void wpi_iter_func(void *, struct ieee80211_node *);
void wpi_amrr_timeout(void *);
-void wpi_amrr_ratectl(void *, struct ieee80211_node *);
+void wpi_newassoc(struct ieee80211com *, struct ieee80211_node *,
+ int);
#define WPI_DEBUG
@@ -332,13 +329,15 @@ wpi_attach(struct device *parent, struct device *self, void *aux)
if_attach(ifp);
ieee80211_ifattach(ifp);
ic->ic_node_alloc = wpi_node_alloc;
- ic->ic_node_copy = wpi_node_copy;
+ ic->ic_newassoc = wpi_newassoc;
/* override state transition machine */
sc->sc_newstate = ic->ic_newstate;
ic->ic_newstate = wpi_newstate;
ieee80211_media_init(ifp, wpi_media_change, ieee80211_media_status);
+ sc->amrr.amrr_min_success_threshold = 1;
+ sc->amrr.amrr_max_success_threshold = 15;
timeout_set(&sc->amrr_ch, wpi_amrr_timeout, sc);
sc->powerhook = powerhook_establish(wpi_power, sc);
@@ -737,26 +736,15 @@ wpi_free_tx_ring(struct wpi_softc *sc, struct wpi_tx_ring *ring)
}
}
-/* ARGSUSED */
struct ieee80211_node *
wpi_node_alloc(struct ieee80211com *ic)
{
- struct wpi_amrr *amrr;
+ struct wpi_node *wn;
- amrr = malloc(sizeof (struct wpi_amrr), M_DEVBUF, M_NOWAIT);
- if (amrr != NULL) {
- bzero(amrr, sizeof (struct wpi_amrr));
- wpi_amrr_init(amrr);
- }
- return (struct ieee80211_node *)amrr;
-}
-
-void
-wpi_node_copy(struct ieee80211com *ic, struct ieee80211_node *dst,
- const struct ieee80211_node *src)
-{
- *dst = *src;
- wpi_amrr_init((struct wpi_amrr *)dst);
+ wn = malloc(sizeof (struct wpi_node), M_DEVBUF, M_NOWAIT);
+ if (wn != NULL)
+ bzero(wn, sizeof (struct wpi_node));
+ return (struct ieee80211_node *)wn;
}
int
@@ -838,6 +826,11 @@ wpi_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
return error;
}
+ if (ic->ic_opmode == IEEE80211_M_STA) {
+ /* fake a join to init the tx rate */
+ wpi_newassoc(ic, ic->ic_bss, 1);
+ }
+
/* start automatic rate control timer */
if (ic->ic_fixed_rate == -1)
timeout_add(&sc->amrr_ch, hz / 2);
@@ -1207,15 +1200,14 @@ wpi_rx_intr(struct wpi_softc *sc, struct wpi_rx_desc *desc,
}
void
-wpi_tx_intr(struct wpi_softc *sc, struct wpi_rx_desc *desc,
- struct wpi_rx_data *data)
+wpi_tx_intr(struct wpi_softc *sc, struct wpi_rx_desc *desc)
{
struct ieee80211com *ic = &sc->sc_ic;
struct ifnet *ifp = &ic->ic_if;
struct wpi_tx_ring *ring = &sc->txq[desc->qid & 0x3];
- struct wpi_tx_data *txdata = &ring->data[desc->idx];
+ struct wpi_tx_data *data = &ring->data[desc->idx];
struct wpi_tx_stat *stat = (struct wpi_tx_stat *)(desc + 1);
- struct wpi_amrr *amrr = (struct wpi_amrr *)txdata->ni;
+ struct wpi_node *wn = (struct wpi_node *)data->ni;
DPRINTFN(4, ("tx done: qid=%d idx=%d retries=%d nkill=%d rate=%x "
"duration=%d status=%x\n", desc->qid, desc->idx, stat->ntries,
@@ -1227,18 +1219,18 @@ wpi_tx_intr(struct wpi_softc *sc, struct wpi_rx_desc *desc,
* XXX we should not count mgmt frames since they're always sent at
* the lowest available bit-rate.
*/
- amrr->txcnt++;
+ wn->amn.amn_txcnt++;
if (stat->ntries > 0) {
DPRINTFN(3, ("tx intr ntries %d\n", stat->ntries));
- amrr->retrycnt++;
+ wn->amn.amn_retrycnt++;
}
- bus_dmamap_unload(sc->sc_dmat, txdata->map);
+ bus_dmamap_unload(sc->sc_dmat, data->map);
- m_freem(txdata->m);
- txdata->m = NULL;
- ieee80211_release_node(ic, txdata->ni);
- txdata->ni = NULL;
+ m_freem(data->m);
+ data->m = NULL;
+ ieee80211_release_node(ic, data->ni);
+ data->ni = NULL;
if ((letoh32(stat->status) & 0xff) != 1)
ifp->if_oerrors++;
@@ -1302,7 +1294,7 @@ wpi_notif_intr(struct wpi_softc *sc)
case WPI_TX_DONE:
/* a 802.11 frame has been transmitted */
- wpi_tx_intr(sc, desc, data);
+ wpi_tx_intr(sc, desc);
break;
case WPI_UC_READY:
@@ -1990,7 +1982,7 @@ wpi_auth(struct wpi_softc *sc)
{
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211_node *ni = ic->ic_bss;
- struct wpi_node node;
+ struct wpi_node_info node;
int error;
/* update adapter's configuration */
@@ -2173,7 +2165,7 @@ wpi_config(struct wpi_softc *sc)
struct wpi_txpower txpower;
struct wpi_power power;
struct wpi_bluetooth bluetooth;
- struct wpi_node node;
+ struct wpi_node_info node;
int error;
/* Intel's binary only daemon is a joke.. */
@@ -2585,52 +2577,13 @@ wpi_stop(struct ifnet *ifp, int disable)
WPI_WRITE(sc, WPI_RESET, tmp | WPI_SW_RESET);
}
-/*-
- * Naive implementation of the Adaptive Multi Rate Retry algorithm:
- * "IEEE 802.11 Rate Adaptation: A Practical Approach"
- * Mathieu Lacage, Hossein Manshaei, Thierry Turletti
- * INRIA Sophia - Projet Planete
- * http://www-sop.inria.fr/rapports/sophia/RR-5208.html
- */
-#define is_success(amrr) \
- ((amrr)->retrycnt < (amrr)->txcnt / 10)
-#define is_failure(amrr) \
- ((amrr)->retrycnt > (amrr)->txcnt / 3)
-#define is_enough(amrr) \
- ((amrr)->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(amrr) \
- do { (amrr)->txcnt = (amrr)->retrycnt = 0; } while (0)
-
-#define WPI_AMRR_MIN_SUCCESS_THRESHOLD 1
-#define WPI_AMRR_MAX_SUCCESS_THRESHOLD 15
-
-/* XXX should reset all nodes on S_INIT */
void
-wpi_amrr_init(struct wpi_amrr *amrr)
+wpi_iter_func(void *arg, struct ieee80211_node *ni)
{
- struct ieee80211_node *ni = &amrr->ni;
- int i;
-
- amrr->success = 0;
- amrr->recovery = 0;
- amrr->txcnt = amrr->retrycnt = 0;
- amrr->success_threshold = WPI_AMRR_MIN_SUCCESS_THRESHOLD;
-
- /* set rate to some reasonable initial value */
- ni = &amrr->ni;
- for (i = ni->ni_rates.rs_nrates - 1;
- i > 0 && (ni->ni_rates.rs_rates[i] & IEEE80211_RATE_VAL) > 72;
- i--);
+ struct wpi_softc *sc = arg;
+ struct wpi_node *wn = (struct wpi_node *)ni;
- ni->ni_txrate = i;
+ ieee80211_amrr_choose(&sc->amrr, ni, &wn->amn);
}
void
@@ -2640,58 +2593,26 @@ wpi_amrr_timeout(void *arg)
struct ieee80211com *ic = &sc->sc_ic;
if (ic->ic_opmode == IEEE80211_M_STA)
- wpi_amrr_ratectl(NULL, ic->ic_bss);
+ wpi_iter_func(sc, ic->ic_bss);
else
- ieee80211_iterate_nodes(ic, wpi_amrr_ratectl, NULL);
+ ieee80211_iterate_nodes(ic, wpi_iter_func, sc);
timeout_add(&sc->amrr_ch, hz / 2);
}
-/* ARGSUSED */
void
-wpi_amrr_ratectl(void *arg, struct ieee80211_node *ni)
+wpi_newassoc(struct ieee80211com *ic, struct ieee80211_node *ni, int isnew)
{
- struct wpi_amrr *amrr = (struct wpi_amrr *)ni;
- int need_change = 0;
-
- if (is_success(amrr) && is_enough(amrr)) {
- amrr->success++;
- if (amrr->success >= amrr->success_threshold &&
- !is_max_rate(ni)) {
- amrr->recovery = 1;
- amrr->success = 0;
- increase_rate(ni);
- DPRINTFN(2, ("AMRR increasing rate %d (txcnt=%d "
- "retrycnt=%d)\n", ni->ni_txrate, amrr->txcnt,
- amrr->retrycnt));
- need_change = 1;
- } else {
- amrr->recovery = 0;
- }
- } else if (is_failure(amrr)) {
- amrr->success = 0;
- if (!is_min_rate(ni)) {
- if (amrr->recovery) {
- amrr->success_threshold *= 2;
- if (amrr->success_threshold >
- WPI_AMRR_MAX_SUCCESS_THRESHOLD)
- amrr->success_threshold =
- WPI_AMRR_MAX_SUCCESS_THRESHOLD;
- } else {
- amrr->success_threshold =
- WPI_AMRR_MIN_SUCCESS_THRESHOLD;
- }
- decrease_rate(ni);
- DPRINTFN(2, ("AMRR decreasing rate %d (txcnt=%d "
- "retrycnt=%d)\n", ni->ni_txrate, amrr->txcnt,
- amrr->retrycnt));
- need_change = 1;
- }
- amrr->recovery = 0; /* paper is incorrect */
- }
+ struct wpi_softc *sc = ic->ic_if.if_softc;
+ int i;
- if (is_enough(amrr) || need_change)
- reset_cnt(amrr);
+ ieee80211_amrr_node_init(&sc->amrr, &((struct wpi_node *)ni)->amn);
+
+ /* set rate to some reasonable initial value */
+ for (i = ni->ni_rates.rs_nrates - 1;
+ i > 0 && (ni->ni_rates.rs_rates[i] & IEEE80211_RATE_VAL) > 72;
+ i--);
+ ni->ni_txrate = i;
}
struct cfdriver wpi_cd = {
diff --git a/sys/dev/pci/if_wpireg.h b/sys/dev/pci/if_wpireg.h
index 29a40f534e2..b0acfe5bfca 100644
--- a/sys/dev/pci/if_wpireg.h
+++ b/sys/dev/pci/if_wpireg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_wpireg.h,v 1.8 2006/06/16 18:54:09 damien Exp $ */
+/* $OpenBSD: if_wpireg.h,v 1.9 2006/06/17 19:07:19 damien Exp $ */
/*-
* Copyright (c) 2006
@@ -317,7 +317,7 @@ struct wpi_cmd_tsf {
} __packed;
/* structure for WPI_CMD_ADD_NODE */
-struct wpi_node {
+struct wpi_node_info {
uint8_t control;
#define WPI_NODE_UPDATE (1 << 0)
diff --git a/sys/dev/pci/if_wpivar.h b/sys/dev/pci/if_wpivar.h
index f80a74426e0..8f3324e90bb 100644
--- a/sys/dev/pci/if_wpivar.h
+++ b/sys/dev/pci/if_wpivar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_wpivar.h,v 1.6 2006/05/25 09:26:58 damien Exp $ */
+/* $OpenBSD: if_wpivar.h,v 1.7 2006/06/17 19:07:19 damien Exp $ */
/*-
* Copyright (c) 2006
@@ -91,13 +91,9 @@ struct wpi_rx_ring {
int cur;
};
-struct wpi_amrr {
- struct ieee80211_node ni; /* must be the first */
- int txcnt;
- int retrycnt;
- int success;
- int success_threshold;
- int recovery;
+struct wpi_node {
+ struct ieee80211_node ni; /* must be the first */
+ struct ieee80211_amrr_node amn;
};
struct wpi_softc {
@@ -106,6 +102,7 @@ struct wpi_softc {
struct ieee80211com sc_ic;
int (*sc_newstate)(struct ieee80211com *,
enum ieee80211_state, int);
+ struct ieee80211_amrr amrr;
uint32_t flags;
#define WPI_FLAG_FW_INITED (1 << 0)
diff --git a/sys/dev/usb/if_ral.c b/sys/dev/usb/if_ral.c
index 416596e4418..fab7af4d47c 100644
--- a/sys/dev/usb/if_ral.c
+++ b/sys/dev/usb/if_ral.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_ral.c,v 1.68 2006/06/10 20:28:11 damien Exp $ */
+/* $OpenBSD: if_ral.c,v 1.69 2006/06/17 19:07:19 damien Exp $ */
/*-
* Copyright (c) 2005, 2006
@@ -56,7 +56,7 @@
#include <netinet/ip.h>
#include <net80211/ieee80211_var.h>
-#include <net80211/ieee80211_rssadapt.h>
+#include <net80211/ieee80211_amrr.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/usb/usb.h>
@@ -171,8 +171,6 @@ Static void ural_amrr_start(struct ural_softc *,
Static void ural_amrr_timeout(void *);
Static void ural_amrr_update(usbd_xfer_handle, usbd_private_handle,
usbd_status status);
-Static void ural_ratectl(struct ural_amrr *,
- struct ieee80211_node *);
/*
* Supported rates for 802.11a/b/g modes (in 500Kbps unit).
@@ -290,6 +288,9 @@ USB_ATTACH(ural)
usb_init_task(&sc->sc_task, ural_task, sc);
timeout_set(&sc->scan_ch, ural_next_scan, sc);
+
+ sc->amrr.amrr_min_success_threshold = 1;
+ sc->amrr.amrr_max_success_threshold = 10;
timeout_set(&sc->amrr_ch, ural_amrr_timeout, sc);
/* retrieve RT2570 rev. no */
@@ -939,7 +940,7 @@ ural_txtime(int len, int rate, uint32_t flags)
uint16_t txtime;
if (RAL_RATE_IS_OFDM(rate)) {
- /* IEEE Std 802.11a-1999, pp. 37 */
+ /* IEEE Std 802.11g-2003, pp. 44 */
txtime = (8 + 4 * len + 3 + rate - 1) / rate;
txtime = 16 + 4 + 4 * txtime + 6;
} else {
@@ -2165,28 +2166,20 @@ ural_stop(struct ifnet *ifp, int disable)
ural_free_tx_list(sc);
}
-#define URAL_AMRR_MIN_SUCCESS_THRESHOLD 1
-#define URAL_AMRR_MAX_SUCCESS_THRESHOLD 10
-
Static void
ural_amrr_start(struct ural_softc *sc, struct ieee80211_node *ni)
{
- struct ural_amrr *amrr = &sc->amrr;
int i;
/* clear statistic registers (STA_CSR0 to STA_CSR10) */
ural_read_multi(sc, RAL_STA_CSR0, sc->sta, sizeof sc->sta);
- amrr->success = 0;
- amrr->recovery = 0;
- amrr->txcnt = amrr->retrycnt = 0;
- amrr->success_threshold = URAL_AMRR_MIN_SUCCESS_THRESHOLD;
+ ieee80211_amrr_node_init(&sc->amrr, &sc->amn);
/* set rate to some reasonable initial value */
for (i = ni->ni_rates.rs_nrates - 1;
i > 0 && (ni->ni_rates.rs_rates[i] & IEEE80211_RATE_VAL) > 72;
i--);
-
ni->ni_txrate = i;
timeout_add(&sc->amrr_ch, hz);
@@ -2223,7 +2216,6 @@ ural_amrr_update(usbd_xfer_handle xfer, usbd_private_handle priv,
usbd_status status)
{
struct ural_softc *sc = (struct ural_softc *)priv;
- struct ural_amrr *amrr = &sc->amrr;
struct ifnet *ifp = &sc->sc_ic.ic_if;
if (status != USBD_NORMAL_COMPLETION) {
@@ -2235,87 +2227,20 @@ ural_amrr_update(usbd_xfer_handle xfer, usbd_private_handle priv,
/* count TX retry-fail as Tx errors */
ifp->if_oerrors += sc->sta[9];
- amrr->retrycnt =
+ sc->amn.amn_retrycnt =
sc->sta[7] + /* TX one-retry ok count */
sc->sta[8] + /* TX more-retry ok count */
sc->sta[9]; /* TX retry-fail count */
- amrr->txcnt =
- amrr->retrycnt +
+ sc->amn.amn_txcnt =
+ sc->amn.amn_retrycnt +
sc->sta[6]; /* TX no-retry ok count */
- ural_ratectl(amrr, sc->sc_ic.ic_bss);
+ ieee80211_amrr_choose(&sc->amrr, sc->sc_ic.ic_bss, &sc->amn);
timeout_add(&sc->amrr_ch, hz);
}
-/*-
- * Naive implementation of the Adaptive Multi Rate Retry algorithm:
- * "IEEE 802.11 Rate Adaptation: A Practical Approach"
- * Mathieu Lacage, Hossein Manshaei, Thierry Turletti
- * INRIA Sophia - Projet Planete
- * http://www-sop.inria.fr/rapports/sophia/RR-5208.html
- *
- * This algorithm is particularly well suited for ural since it does not
- * require per-frame retry statistics. Note however that since h/w does
- * not provide per-frame stats, we can't do per-node rate adaptation and
- * thus automatic rate adaptation is only enabled in STA operating mode.
- */
-#define is_success(amrr) \
- ((amrr)->retrycnt < (amrr)->txcnt / 10)
-#define is_failure(amrr) \
- ((amrr)->retrycnt > (amrr)->txcnt / 3)
-#define is_enough(amrr) \
- ((amrr)->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(amrr) \
- do { (amrr)->txcnt = (amrr)->retrycnt = 0; } while (0)
-Static void
-ural_ratectl(struct ural_amrr *amrr, struct ieee80211_node *ni)
-{
- int need_change = 0;
-
- if (is_success(amrr) && is_enough(amrr)) {
- amrr->success++;
- if (amrr->success >= amrr->success_threshold &&
- !is_max_rate(ni)) {
- amrr->recovery = 1;
- amrr->success = 0;
- increase_rate(ni);
- need_change = 1;
- } else {
- amrr->recovery = 0;
- }
- } else if (is_failure(amrr)) {
- amrr->success = 0;
- if (!is_min_rate(ni)) {
- if (amrr->recovery) {
- amrr->success_threshold *= 2;
- if (amrr->success_threshold >
- URAL_AMRR_MAX_SUCCESS_THRESHOLD)
- amrr->success_threshold =
- URAL_AMRR_MAX_SUCCESS_THRESHOLD;
- } else {
- amrr->success_threshold =
- URAL_AMRR_MIN_SUCCESS_THRESHOLD;
- }
- decrease_rate(ni);
- need_change = 1;
- }
- amrr->recovery = 0; /* original paper was incorrect */
- }
-
- if (is_enough(amrr) || need_change)
- reset_cnt(amrr);
-}
-
Static int
ural_activate(device_ptr_t self, enum devact act)
{
diff --git a/sys/dev/usb/if_ralvar.h b/sys/dev/usb/if_ralvar.h
index ae72dd050dd..28df058f44f 100644
--- a/sys/dev/usb/if_ralvar.h
+++ b/sys/dev/usb/if_ralvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_ralvar.h,v 1.5 2006/03/21 11:19:22 pedro Exp $ */
+/* $OpenBSD: if_ralvar.h,v 1.6 2006/06/17 19:07:19 damien Exp $ */
/*-
* Copyright (c) 2005
@@ -69,79 +69,72 @@ struct ural_rx_data {
struct mbuf *m;
};
-struct ural_amrr {
- int txcnt;
- int retrycnt;
- int success;
- int success_threshold;
- int recovery;
-};
-
struct ural_softc {
- USBBASEDEVICE sc_dev;
- struct ieee80211com sc_ic;
- int (*sc_newstate)(struct ieee80211com *,
- enum ieee80211_state, int);
+ USBBASEDEVICE sc_dev;
+ struct ieee80211com sc_ic;
+ int (*sc_newstate)(struct ieee80211com *,
+ enum ieee80211_state, int);
- usbd_device_handle sc_udev;
- usbd_interface_handle sc_iface;
+ usbd_device_handle sc_udev;
+ usbd_interface_handle sc_iface;
- int sc_rx_no;
- int sc_tx_no;
+ int sc_rx_no;
+ int sc_tx_no;
- uint32_t asic_rev;
- uint16_t macbbp_rev;
- uint8_t rf_rev;
+ uint32_t asic_rev;
+ uint16_t macbbp_rev;
+ uint8_t rf_rev;
- usbd_xfer_handle amrr_xfer;
+ usbd_xfer_handle amrr_xfer;
- usbd_pipe_handle sc_rx_pipeh;
- usbd_pipe_handle sc_tx_pipeh;
+ usbd_pipe_handle sc_rx_pipeh;
+ usbd_pipe_handle sc_tx_pipeh;
- enum ieee80211_state sc_state;
- struct usb_task sc_task;
+ enum ieee80211_state sc_state;
+ struct usb_task sc_task;
- struct ural_amrr amrr;
+ struct ieee80211_amrr amrr;
+ struct ieee80211_amrr_node amn;
- struct ural_rx_data rx_data[RAL_RX_LIST_COUNT];
- struct ural_tx_data tx_data[RAL_TX_LIST_COUNT];
- int tx_queued;
+ struct ural_rx_data rx_data[RAL_RX_LIST_COUNT];
+ struct ural_tx_data tx_data[RAL_TX_LIST_COUNT];
+ int tx_queued;
- struct timeout scan_ch;
- struct timeout amrr_ch;
+ struct timeout scan_ch;
+ struct timeout amrr_ch;
- int sc_tx_timer;
+ int sc_tx_timer;
- uint16_t sta[11];
- uint32_t rf_regs[4];
- uint8_t txpow[14];
+ uint16_t sta[11];
+ uint32_t rf_regs[4];
+ uint8_t txpow[14];
struct {
uint8_t val;
uint8_t reg;
- } __packed bbp_prom[16];
+ } __packed bbp_prom[16];
- int led_mode;
- int hw_radio;
- int rx_ant;
- int tx_ant;
- int nb_ant;
+ int led_mode;
+ int hw_radio;
+ int rx_ant;
+ int tx_ant;
+ int nb_ant;
#if NBPFILTER > 0
- caddr_t sc_drvbpf;
+ caddr_t sc_drvbpf;
union {
struct ural_rx_radiotap_header th;
uint8_t pad[64];
- } sc_rxtapu;
+ } sc_rxtapu;
#define sc_rxtap sc_rxtapu.th
- int sc_rxtap_len;
+ int sc_rxtap_len;
union {
struct ural_tx_radiotap_header th;
uint8_t pad[64];
- } sc_txtapu;
+ } sc_txtapu;
#define sc_txtap sc_txtapu.th
- int sc_txtap_len;
+ int sc_txtap_len;
#endif
};
diff --git a/sys/net80211/ieee80211_amrr.c b/sys/net80211/ieee80211_amrr.c
new file mode 100644
index 00000000000..25c6fcd1f2d
--- /dev/null
+++ b/sys/net80211/ieee80211_amrr.c
@@ -0,0 +1,115 @@
+/* $OpenBSD: ieee80211_amrr.c,v 1.1 2006/06/17 19:07:19 damien Exp $ */
+
+/*-
+ * Copyright (c) 2006
+ * Damien Bergamini <damien.bergamini@free.fr>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+
+#include <net/if.h>
+#include <net/if_media.h>
+
+#ifdef INET
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+#endif
+
+#include <net80211/ieee80211.h>
+#include <net80211/ieee80211_var.h>
+#include <net80211/ieee80211_amrr.h>
+
+#define is_success(amn) \
+ ((amn)->amn_retrycnt < (amn)->amn_txcnt / 10)
+#define is_failure(amn) \
+ ((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)
+
+void
+ieee80211_amrr_node_init(struct ieee80211_amrr *amrr,
+ struct ieee80211_amrr_node *amn)
+{
+ amn->amn_success = 0;
+ amn->amn_recovery = 0;
+ amn->amn_txcnt = amn->amn_retrycnt = 0;
+ amn->amn_success_threshold = amrr->amrr_min_success_threshold;
+}
+
+/*
+ * Update ni->ni_txrate.
+ */
+void
+ieee80211_amrr_choose(struct ieee80211_amrr *amrr, struct ieee80211_node *ni,
+ struct ieee80211_amrr_node *amn)
+{
+ int need_change = 0;
+
+ if (is_success(amn) && is_enough(amn)) {
+ amn->amn_success++;
+ if (amn->amn_success >= amn->amn_success_threshold &&
+ !is_max_rate(ni)) {
+ amn->amn_recovery = 1;
+ amn->amn_success = 0;
+ increase_rate(ni);
+ IEEE80211_DPRINTF(("AMRR increasing rate %d (txcnt=%d "
+ "retrycnt=%d)\n",
+ ni->ni_rates.rs_rates[ni->ni_txrate] &
+ 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 (amn->amn_recovery) {
+ amn->amn_success_threshold *= 2;
+ if (amn->amn_success_threshold >
+ amrr->amrr_max_success_threshold)
+ amn->amn_success_threshold =
+ amrr->amrr_max_success_threshold;
+ } else {
+ amn->amn_success_threshold =
+ amrr->amrr_min_success_threshold;
+ }
+ decrease_rate(ni);
+ IEEE80211_DPRINTF(("AMRR decreasing rate %d (txcnt=%d "
+ "retrycnt=%d)\n",
+ ni->ni_rates.rs_rates[ni->ni_txrate] &
+ 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);
+}
diff --git a/sys/net80211/ieee80211_amrr.h b/sys/net80211/ieee80211_amrr.h
new file mode 100644
index 00000000000..5e49b3e9249
--- /dev/null
+++ b/sys/net80211/ieee80211_amrr.h
@@ -0,0 +1,54 @@
+/* $OpenBSD: ieee80211_amrr.h,v 1.1 2006/06/17 19:07:19 damien Exp $ */
+
+/*-
+ * Copyright (c) 2006
+ * Damien Bergamini <damien.bergamini@free.fr>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*-
+ * Naive implementation of the Adaptive Multi Rate Retry algorithm:
+ *
+ * "IEEE 802.11 Rate Adaptation: A Practical Approach"
+ * Mathieu Lacage, Hossein Manshaei, Thierry Turletti
+ * INRIA Sophia - Projet Planete
+ * http://www-sop.inria.fr/rapports/sophia/RR-5208.html
+ */
+
+/*
+ * Rate control settings.
+ */
+struct ieee80211_amrr {
+ int amrr_min_success_threshold;
+ int amrr_max_success_threshold;
+};
+
+#define IEEE80211_AMRR_MIN_SUCCESS_THRESHOLD 1
+#define IEEE80211_AMRR_MAX_SUCCESS_THRESHOLD 15
+
+/*
+ * Rate control state for a given node.
+ */
+struct ieee80211_amrr_node {
+ int amn_success;
+ int amn_recovery;
+ int amn_success_threshold;
+ int amn_txcnt;
+ int amn_retrycnt;
+};
+
+void ieee80211_amrr_node_init(struct ieee80211_amrr *,
+ struct ieee80211_amrr_node *);
+void ieee80211_amrr_choose(struct ieee80211_amrr *, struct ieee80211_node *,
+ struct ieee80211_amrr_node *);