diff options
author | Damien Bergamini <damien@cvs.openbsd.org> | 2006-06-17 19:07:20 +0000 |
---|---|---|
committer | Damien Bergamini <damien@cvs.openbsd.org> | 2006-06-17 19:07:20 +0000 |
commit | 450bd603f12aa3967b92c42500ad81f481d392f0 (patch) | |
tree | b5858fbb9926989a29a6f8fc9ece501364d78ced | |
parent | 0687c41ffcf408ac7d8bdbf417add41082bfc17e (diff) |
Move AMRR rate control algorithm out of wpi(4) and ural(4), into net80211.
ok brad@
-rw-r--r-- | sys/conf/files | 3 | ||||
-rw-r--r-- | sys/dev/pci/if_wpi.c | 175 | ||||
-rw-r--r-- | sys/dev/pci/if_wpireg.h | 4 | ||||
-rw-r--r-- | sys/dev/pci/if_wpivar.h | 13 | ||||
-rw-r--r-- | sys/dev/usb/if_ral.c | 97 | ||||
-rw-r--r-- | sys/dev/usb/if_ralvar.h | 85 | ||||
-rw-r--r-- | sys/net80211/ieee80211_amrr.c | 115 | ||||
-rw-r--r-- | sys/net80211/ieee80211_amrr.h | 54 |
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 *); |