diff options
34 files changed, 649 insertions, 609 deletions
diff --git a/sys/conf/files b/sys/conf/files index 572eb5f..61e1d64 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -2370,6 +2370,7 @@ net80211/ieee80211_phy.c optional wlan net80211/ieee80211_power.c optional wlan net80211/ieee80211_proto.c optional wlan net80211/ieee80211_radiotap.c optional wlan +net80211/ieee80211_ratectl.c optional wlan net80211/ieee80211_regdomain.c optional wlan net80211/ieee80211_rssadapt.c optional wlan wlan_rssadapt net80211/ieee80211_scan.c optional wlan diff --git a/sys/dev/bwi/if_bwi.c b/sys/dev/bwi/if_bwi.c index 327b736..20ea2d5 100644 --- a/sys/dev/bwi/if_bwi.c +++ b/sys/dev/bwi/if_bwi.c @@ -64,8 +64,8 @@ __FBSDID("$FreeBSD$"); #include <net80211/ieee80211_var.h> #include <net80211/ieee80211_radiotap.h> #include <net80211/ieee80211_regdomain.h> -#include <net80211/ieee80211_amrr.h> #include <net80211/ieee80211_phy.h> +#include <net80211/ieee80211_ratectl.h> #include <net/bpf.h> @@ -112,9 +112,6 @@ static void bwi_set_channel(struct ieee80211com *); static void bwi_scan_end(struct ieee80211com *); static int bwi_newstate(struct ieee80211vap *, enum ieee80211_state, int); static void bwi_updateslot(struct ifnet *); -static struct ieee80211_node *bwi_node_alloc(struct ieee80211vap *, - const uint8_t [IEEE80211_ADDR_LEN]); -static void bwi_newassoc(struct ieee80211_node *, int); static int bwi_media_change(struct ifnet *); static void bwi_calibrate(void *); @@ -525,7 +522,6 @@ bwi_attach(struct bwi_softc *sc) ic->ic_vap_delete = bwi_vap_delete; ic->ic_raw_xmit = bwi_raw_xmit; ic->ic_updateslot = bwi_updateslot; - ic->ic_node_alloc = bwi_node_alloc; ic->ic_scan_start = bwi_scan_start; ic->ic_scan_end = bwi_scan_end; ic->ic_set_channel = bwi_set_channel; @@ -620,10 +616,7 @@ bwi_vap_create(struct ieee80211com *ic, #if 0 vap->iv_update_beacon = bwi_beacon_update; #endif - ieee80211_amrr_init(&bvp->bv_amrr, vap, - IEEE80211_AMRR_MIN_SUCCESS_THRESHOLD, - IEEE80211_AMRR_MAX_SUCCESS_THRESHOLD, - 500 /*ms*/); + ieee80211_ratectl_init(vap); /* complete setup */ ieee80211_vap_attach(vap, bwi_media_change, ieee80211_media_status); @@ -636,7 +629,7 @@ bwi_vap_delete(struct ieee80211vap *vap) { struct bwi_vap *bvp = BWI_VAP(vap); - ieee80211_amrr_cleanup(&bvp->bv_amrr); + ieee80211_ratectl_deinit(vap); ieee80211_vap_detach(vap); free(bvp, M_80211_VAP); } @@ -1826,7 +1819,7 @@ bwi_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) #endif if (vap->iv_opmode == IEEE80211_M_STA) { /* fake a join to init the tx rate */ - bwi_newassoc(ni, 1); + ic->ic_newassoc(ni, 1); } callout_reset(&sc->sc_calib_ch, hz, bwi_calibrate, sc); @@ -1837,25 +1830,6 @@ back: return error; } -/* ARGUSED */ -static struct ieee80211_node * -bwi_node_alloc(struct ieee80211vap *vap, const uint8_t mac[IEEE80211_ADDR_LEN]) -{ - struct bwi_node *bn; - - bn = malloc(sizeof(struct bwi_node), M_80211_NODE, M_NOWAIT | M_ZERO); - return bn != NULL ? &bn->ni : NULL; -} - -static void -bwi_newassoc(struct ieee80211_node *ni, int isnew) -{ - struct ieee80211vap *vap = ni->ni_vap; - - ieee80211_amrr_node_init(&BWI_VAP(vap)->bv_amrr, - &BWI_NODE(ni)->amn, ni); -} - static int bwi_media_change(struct ifnet *ifp) { @@ -3007,7 +2981,7 @@ bwi_encap(struct bwi_softc *sc, int idx, struct mbuf *m, } else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE) { rate = rate_fb = tp->ucastrate; } else { - rix = ieee80211_amrr_choose(ni, &BWI_NODE(ni)->amn); + rix = ieee80211_ratectl_rate(ni, NULL, pkt_len); rate = ni->ni_txrate; if (rix > 0) { @@ -3364,6 +3338,7 @@ _bwi_txeof(struct bwi_softc *sc, uint16_t tx_id, int acked, int data_txcnt) struct bwi_txbuf *tb; int ring_idx, buf_idx; struct ieee80211_node *ni; + struct ieee80211vap *vap; if (tx_id == 0) { if_printf(ifp, "%s: zero tx id\n", __func__); @@ -3389,9 +3364,9 @@ _bwi_txeof(struct bwi_softc *sc, uint16_t tx_id, int acked, int data_txcnt) ni = tb->tb_ni; if (tb->tb_ni != NULL) { - struct bwi_node *bn = (struct bwi_node *) tb->tb_ni; const struct bwi_txbuf_hdr *hdr = mtod(tb->tb_mbuf, const struct bwi_txbuf_hdr *); + vap = ni->ni_vap; /* NB: update rate control only for unicast frames */ if (hdr->txh_mac_ctrl & htole32(BWI_TXH_MAC_C_ACK)) { @@ -3402,8 +3377,9 @@ _bwi_txeof(struct bwi_softc *sc, uint16_t tx_id, int acked, int data_txcnt) * well so to avoid over-aggressive downshifting we * treat any number of retries as "1". */ - ieee80211_amrr_tx_complete(&bn->amn, acked, - data_txcnt > 1); + ieee80211_ratectl_tx_complete(vap, ni, + (data_txcnt > 1) ? IEEE80211_RATECTL_TX_SUCCESS : + IEEE80211_RATECTL_TX_FAILURE, &acked, NULL); } /* diff --git a/sys/dev/bwi/if_bwivar.h b/sys/dev/bwi/if_bwivar.h index af4b0ea..39b7b7c 100644 --- a/sys/dev/bwi/if_bwivar.h +++ b/sys/dev/bwi/if_bwivar.h @@ -533,15 +533,8 @@ struct bwi_rx_radiotap_hdr { /* TODO: sq */ }; -struct bwi_node { - struct ieee80211_node ni; /* must be the first */ - struct ieee80211_amrr_node amn; -}; -#define BWI_NODE(ni) ((struct bwi_node *)(ni)) - struct bwi_vap { struct ieee80211vap bv_vap; - struct ieee80211_amrr bv_amrr; int (*bv_newstate)(struct ieee80211vap *, enum ieee80211_state, int); }; diff --git a/sys/dev/bwn/if_bwn.c b/sys/dev/bwn/if_bwn.c index c6c192e..5ca5098 100644 --- a/sys/dev/bwn/if_bwn.c +++ b/sys/dev/bwn/if_bwn.c @@ -67,8 +67,8 @@ __FBSDID("$FreeBSD$"); #include <net80211/ieee80211_var.h> #include <net80211/ieee80211_radiotap.h> #include <net80211/ieee80211_regdomain.h> -#include <net80211/ieee80211_amrr.h> #include <net80211/ieee80211_phy.h> +#include <net80211/ieee80211_ratectl.h> #include <dev/bwn/if_bwnreg.h> #include <dev/bwn/if_bwnvar.h> @@ -180,18 +180,14 @@ static void bwn_addchannels(struct ieee80211_channel [], int, int *, const struct bwn_channelinfo *, int); static int bwn_raw_xmit(struct ieee80211_node *, struct mbuf *, const struct ieee80211_bpf_params *); -static void bwn_newassoc(struct ieee80211_node *, int); static void bwn_updateslot(struct ifnet *); static void bwn_update_promisc(struct ifnet *); static void bwn_wme_init(struct bwn_mac *); static int bwn_wme_update(struct ieee80211com *); -static struct ieee80211_node *bwn_node_alloc(struct ieee80211vap *, - const uint8_t [IEEE80211_ADDR_LEN]); static void bwn_wme_clear(struct bwn_softc *); static void bwn_wme_load(struct bwn_mac *); static void bwn_wme_loadparams(struct bwn_mac *, const struct wmeParams *, uint16_t); -static void bwn_node_cleanup(struct ieee80211_node *); static void bwn_scan_start(struct ieee80211com *); static void bwn_scan_end(struct ieee80211com *); static void bwn_set_channel(struct ieee80211com *); @@ -1088,15 +1084,10 @@ bwn_attach_post(struct bwn_softc *sc) /* override default methods */ ic->ic_raw_xmit = bwn_raw_xmit; - ic->ic_newassoc = bwn_newassoc; ic->ic_updateslot = bwn_updateslot; ic->ic_update_promisc = bwn_update_promisc; ic->ic_wme.wme_update = bwn_wme_update; - ic->ic_node_alloc = bwn_node_alloc; - sc->sc_node_cleanup = ic->ic_node_cleanup; - ic->ic_node_cleanup = bwn_node_cleanup; - ic->ic_scan_start = bwn_scan_start; ic->ic_scan_end = bwn_scan_end; ic->ic_set_channel = bwn_set_channel; @@ -2772,20 +2763,6 @@ bwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, } /* - * Setup driver-specific state for a newly associated node. - * Note that we're called also on a re-associate, the isnew - * param tells us if this is the first time or not. - */ -static void -bwn_newassoc(struct ieee80211_node *ni, int isnew) -{ - struct ieee80211vap *vap = ni->ni_vap; - - ieee80211_amrr_node_init(&BWN_VAP(vap)->bv_amrr, - &BWN_NODE(ni)->bn_amn, ni); -} - -/* * Callback from the 802.11 layer to update the slot time * based on the current setting. We use it to notify the * firmware of ERP changes and the f/w takes care of things @@ -2857,32 +2834,6 @@ bwn_wme_update(struct ieee80211com *ic) return (0); } -static struct ieee80211_node * -bwn_node_alloc(struct ieee80211vap *vap, const uint8_t mac[IEEE80211_ADDR_LEN]) -{ - struct ieee80211com *ic = vap->iv_ic; - struct bwn_softc *sc = ic->ic_ifp->if_softc; - const size_t space = sizeof(struct bwn_node); - struct bwn_node *bn; - - bn = malloc(space, M_80211_NODE, M_NOWAIT|M_ZERO); - if (bn == NULL) { - /* XXX stat+msg */ - return (NULL); - } - DPRINTF(sc, BWN_DEBUG_NODE, "%s: bn %p\n", __func__, bn); - return (&bn->bn_node); -} - -static void -bwn_node_cleanup(struct ieee80211_node *ni) -{ - struct ieee80211com *ic = ni->ni_ic; - struct bwn_softc *sc = ic->ic_ifp->if_softc; - - sc->sc_node_cleanup(ni); -} - static void bwn_scan_start(struct ieee80211com *ic) { @@ -3018,10 +2969,7 @@ bwn_vap_create(struct ieee80211com *ic, /* override max aid so sta's cannot assoc when we're out of sta id's */ vap->iv_max_aid = BWN_STAID_MAX; - ieee80211_amrr_init(&bvp->bv_amrr, vap, - IEEE80211_AMRR_MIN_SUCCESS_THRESHOLD, - IEEE80211_AMRR_MAX_SUCCESS_THRESHOLD, - 500 /*ms*/); + ieee80211_ratectl_init(vap); /* complete setup */ ieee80211_vap_attach(vap, ieee80211_media_change, @@ -3034,7 +2982,7 @@ bwn_vap_delete(struct ieee80211vap *vap) { struct bwn_vap *bvp = BWN_VAP(vap); - ieee80211_amrr_cleanup(&bvp->bv_amrr); + ieee80211_ratectl_deinit(vap); ieee80211_vap_detach(vap); free(bvp, M_80211_VAP); } @@ -9040,12 +8988,12 @@ bwn_handle_txeof(struct bwn_mac *mac, const struct bwn_txstatus *status) struct bwn_dma_ring *dr; struct bwn_dmadesc_generic *desc; struct bwn_dmadesc_meta *meta; - struct bwn_node *bn; struct bwn_pio_txqueue *tq; struct bwn_pio_txpkt *tp = NULL; struct bwn_softc *sc = mac->mac_sc; struct bwn_stats *stats = &mac->mac_stats; struct ieee80211_node *ni; + struct ieee80211vap *vap; int slot; BWN_ASSERT_LOCKED(mac->mac_sc); @@ -9074,9 +9022,12 @@ bwn_handle_txeof(struct bwn_mac *mac, const struct bwn_txstatus *status) dr->getdesc(dr, slot, &desc, &meta); if (meta->mt_islast) { ni = meta->mt_ni; - bn = (struct bwn_node *)ni; - ieee80211_amrr_tx_complete(&bn->bn_amn, - status->ack, 0); + vap = ni->ni_vap; + ieee80211_ratectl_tx_complete(vap, ni, + status->ack ? + IEEE80211_RATECTL_TX_SUCCESS : + IEEE80211_RATECTL_TX_FAILURE, + NULL, 0); break; } slot = bwn_dma_nextslot(dr, slot); @@ -9092,8 +9043,12 @@ bwn_handle_txeof(struct bwn_mac *mac, const struct bwn_txstatus *status) return; } ni = tp->tp_ni; - bn = (struct bwn_node *)ni; - ieee80211_amrr_tx_complete(&bn->bn_amn, status->ack, 0); + vap = ni->ni_vap; + ieee80211_ratectl_tx_complete(vap, ni, + status->ack ? + IEEE80211_RATECTL_TX_SUCCESS : + IEEE80211_RATECTL_TX_FAILURE, + NULL, 0); } bwn_pio_handle_txeof(mac, status); } @@ -9680,7 +9635,7 @@ bwn_set_txhdr(struct bwn_mac *mac, struct ieee80211_node *ni, else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE) rate = rate_fb = tp->ucastrate; else { - rix = ieee80211_amrr_choose(ni, &BWN_NODE(ni)->bn_amn); + rix = ieee80211_ratectl_rate(ni, NULL, 0); rate = ni->ni_txrate; if (rix > 0) diff --git a/sys/dev/bwn/if_bwnvar.h b/sys/dev/bwn/if_bwnvar.h index 16934c3..461587d 100644 --- a/sys/dev/bwn/if_bwnvar.h +++ b/sys/dev/bwn/if_bwnvar.h @@ -883,18 +883,11 @@ struct bwn_mac { TAILQ_ENTRY(bwn_mac) mac_list; }; -struct bwn_node { - struct ieee80211_node bn_node; /* must be the first */ - struct ieee80211_amrr_node bn_amn; -}; -#define BWN_NODE(ni) ((struct bwn_node *)(ni)) - /* * Driver-specific vap state. */ struct bwn_vap { struct ieee80211vap bv_vap; /* base class */ - struct ieee80211_amrr bv_amrr; int (*bv_newstate)(struct ieee80211vap *, enum ieee80211_state, int); }; diff --git a/sys/dev/iwn/if_iwn.c b/sys/dev/iwn/if_iwn.c index be8c7c7..09c1efd 100644 --- a/sys/dev/iwn/if_iwn.c +++ b/sys/dev/iwn/if_iwn.c @@ -65,9 +65,9 @@ __FBSDID("$FreeBSD$"); #include <netinet/ip.h> #include <net80211/ieee80211_var.h> -#include <net80211/ieee80211_amrr.h> #include <net80211/ieee80211_radiotap.h> #include <net80211/ieee80211_regdomain.h> +#include <net80211/ieee80211_ratectl.h> #include <dev/iwn/if_iwnreg.h> #include <dev/iwn/if_iwnvar.h> @@ -785,11 +785,7 @@ iwn_vap_create(struct ieee80211com *ic, ivp->iv_newstate = vap->iv_newstate; vap->iv_newstate = iwn_newstate; - ieee80211_amrr_init(&ivp->iv_amrr, vap, - IEEE80211_AMRR_MIN_SUCCESS_THRESHOLD, - IEEE80211_AMRR_MAX_SUCCESS_THRESHOLD, - 500 /* ms */); - + ieee80211_ratectl_init(vap); /* Complete setup. */ ieee80211_vap_attach(vap, iwn_media_change, ieee80211_media_status); ic->ic_opmode = opmode; @@ -801,7 +797,7 @@ iwn_vap_delete(struct ieee80211vap *vap) { struct iwn_vap *ivp = IWN_VAP(vap); - ieee80211_amrr_cleanup(&ivp->iv_amrr); + ieee80211_ratectl_deinit(vap); ieee80211_vap_detach(vap); free(ivp, M_80211_VAP); } @@ -1897,11 +1893,8 @@ iwn_node_alloc(struct ieee80211vap *vap, const uint8_t mac[IEEE80211_ADDR_LEN]) static void iwn_newassoc(struct ieee80211_node *ni, int isnew) { - struct ieee80211vap *vap = ni->ni_vap; - struct iwn_node *wn = (void *)ni; - - ieee80211_amrr_node_init(&IWN_VAP(vap)->iv_amrr, - &wn->amn, ni); + /* XXX move */ + ieee80211_ratectl_node_init(ni); } static int @@ -2333,9 +2326,9 @@ iwn_tx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc, int ackfailcnt, struct ifnet *ifp = sc->sc_ifp; struct iwn_tx_ring *ring = &sc->txq[desc->qid & 0xf]; struct iwn_tx_data *data = &ring->data[desc->idx]; - struct iwn_node *wn = (void *)data->ni; struct mbuf *m; struct ieee80211_node *ni; + struct ieee80211vap *vap; KASSERT(data->ni != NULL, ("no node")); @@ -2344,6 +2337,7 @@ iwn_tx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc, int ackfailcnt, bus_dmamap_unload(ring->data_dmat, data->map); m = data->m, data->m = NULL; ni = data->ni, data->ni = NULL; + vap = ni->ni_vap; if (m->m_flags & M_TXCB) { /* @@ -2373,11 +2367,11 @@ iwn_tx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc, int ackfailcnt, */ if (status & 0x80) { ifp->if_oerrors++; - ieee80211_amrr_tx_complete(&wn->amn, - IEEE80211_AMRR_FAILURE, ackfailcnt); + ieee80211_ratectl_tx_complete(vap, ni, + IEEE80211_RATECTL_TX_FAILURE, &ackfailcnt, NULL); } else { - ieee80211_amrr_tx_complete(&wn->amn, - IEEE80211_AMRR_SUCCESS, ackfailcnt); + ieee80211_ratectl_tx_complete(vap, ni, + IEEE80211_RATECTL_TX_SUCCESS, &ackfailcnt, NULL); } m_freem(m); ieee80211_free_node(ni); @@ -2897,7 +2891,8 @@ iwn_tx_data(struct iwn_softc *sc, struct mbuf *m, struct ieee80211_node *ni, else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE) rate = tp->ucastrate; else { - (void) ieee80211_amrr_choose(ni, &wn->amn); + /* XXX pass pktlen */ + (void) ieee80211_ratectl_rate(ni, NULL, 0); rate = ni->ni_txrate; } ridx = iwn_plcp_signal(rate); @@ -6480,4 +6475,3 @@ DRIVER_MODULE(iwn, pci, iwn_driver, iwn_devclass, 0, 0); MODULE_DEPEND(iwn, pci, 1, 1, 1); MODULE_DEPEND(iwn, firmware, 1, 1, 1); MODULE_DEPEND(iwn, wlan, 1, 1, 1); -MODULE_DEPEND(iwn, wlan_amrr, 1, 1, 1); diff --git a/sys/dev/iwn/if_iwnvar.h b/sys/dev/iwn/if_iwnvar.h index 7b4ad98..40ce30f 100644 --- a/sys/dev/iwn/if_iwnvar.h +++ b/sys/dev/iwn/if_iwnvar.h @@ -99,7 +99,6 @@ struct iwn_rx_ring { struct iwn_node { struct ieee80211_node ni; /* must be the first */ - struct ieee80211_amrr_node amn; uint16_t disable_tid; uint8_t id; uint8_t ridx[IEEE80211_RATE_MAXSIZE]; @@ -193,8 +192,6 @@ struct iwn_hal { struct iwn_vap { struct ieee80211vap iv_vap; - struct ieee80211_amrr iv_amrr; - struct callout iv_amrr_to; uint8_t iv_ridx; int (*iv_newstate)(struct ieee80211vap *, diff --git a/sys/dev/ral/rt2560.c b/sys/dev/ral/rt2560.c index 455b5ad..9549107 100644 --- a/sys/dev/ral/rt2560.c +++ b/sys/dev/ral/rt2560.c @@ -54,7 +54,7 @@ __FBSDID("$FreeBSD$"); #include <net80211/ieee80211_var.h> #include <net80211/ieee80211_radiotap.h> #include <net80211/ieee80211_regdomain.h> -#include <net80211/ieee80211_amrr.h> +#include <net80211/ieee80211_ratectl.h> #include <netinet/in.h> #include <netinet/in_systm.h> @@ -103,8 +103,6 @@ static void rt2560_reset_rx_ring(struct rt2560_softc *, struct rt2560_rx_ring *); static void rt2560_free_rx_ring(struct rt2560_softc *, struct rt2560_rx_ring *); -static struct ieee80211_node *rt2560_node_alloc(struct ieee80211vap *, - const uint8_t [IEEE80211_ADDR_LEN]); static void rt2560_newassoc(struct ieee80211_node *, int); static int rt2560_newstate(struct ieee80211vap *, enum ieee80211_state, int); @@ -307,7 +305,6 @@ rt2560_attach(device_t dev, int id) ic->ic_raw_xmit = rt2560_raw_xmit; ic->ic_updateslot = rt2560_update_slot; ic->ic_update_promisc = rt2560_update_promisc; - ic->ic_node_alloc = rt2560_node_alloc; ic->ic_scan_start = rt2560_scan_start; ic->ic_scan_end = rt2560_scan_end; ic->ic_set_channel = rt2560_set_channel; @@ -430,11 +427,7 @@ rt2560_vap_create(struct ieee80211com *ic, vap->iv_newstate = rt2560_newstate; vap->iv_update_beacon = rt2560_beacon_update; - ieee80211_amrr_init(&rvp->amrr, vap, - IEEE80211_AMRR_MIN_SUCCESS_THRESHOLD, - IEEE80211_AMRR_MAX_SUCCESS_THRESHOLD, - 500 /* ms */); - + ieee80211_ratectl_init(vap); /* complete setup */ ieee80211_vap_attach(vap, ieee80211_media_change, ieee80211_media_status); if (TAILQ_FIRST(&ic->ic_vaps) == vap) @@ -447,7 +440,7 @@ rt2560_vap_delete(struct ieee80211vap *vap) { struct rt2560_vap *rvp = RT2560_VAP(vap); - ieee80211_amrr_cleanup(&rvp->amrr); + ieee80211_ratectl_deinit(vap); ieee80211_vap_detach(vap); free(rvp, M_80211_VAP); } @@ -764,25 +757,11 @@ rt2560_free_rx_ring(struct rt2560_softc *sc, struct rt2560_rx_ring *ring) bus_dma_tag_destroy(ring->data_dmat); } -static struct ieee80211_node * -rt2560_node_alloc(struct ieee80211vap *vap, - const uint8_t mac[IEEE80211_ADDR_LEN]) -{ - struct rt2560_node *rn; - - rn = malloc(sizeof (struct rt2560_node), M_80211_NODE, - M_NOWAIT | M_ZERO); - - return (rn != NULL) ? &rn->ni : NULL; -} - static void rt2560_newassoc(struct ieee80211_node *ni, int isnew) { - struct ieee80211vap *vap = ni->ni_vap; - - ieee80211_amrr_node_init(&RT2560_VAP(vap)->amrr, - &RT2560_NODE(ni)->amrr, ni); + /* XXX move */ + ieee80211_ratectl_node_init(ni); } static int @@ -955,10 +934,11 @@ rt2560_tx_intr(struct rt2560_softc *sc) struct ifnet *ifp = sc->sc_ifp; struct rt2560_tx_desc *desc; struct rt2560_tx_data *data; - struct rt2560_node *rn; struct mbuf *m; uint32_t flags; int retrycnt; + struct ieee80211vap *vap; + struct ieee80211_node *ni; bus_dmamap_sync(sc->txq.desc_dmat, sc->txq.desc_map, BUS_DMASYNC_POSTREAD); @@ -973,15 +953,19 @@ rt2560_tx_intr(struct rt2560_softc *sc) !(flags & RT2560_TX_VALID)) break; - rn = (struct rt2560_node *)data->ni; m = data->m; + ni = data->ni; + vap = ni->ni_vap; switch (flags & RT2560_TX_RESULT_MASK) { case RT2560_TX_SUCCESS: + retrycnt = 0; + DPRINTFN(sc, 10, "%s\n", "data frame sent successfully"); if (data->rix != IEEE80211_FIXED_RATE_NONE) - ieee80211_amrr_tx_complete(&rn->amrr, - IEEE80211_AMRR_SUCCESS, 0); + ieee80211_ratectl_tx_complete(vap, ni, + IEEE80211_RATECTL_TX_SUCCESS, + &retrycnt, NULL); ifp->if_opackets++; break; @@ -991,8 +975,9 @@ rt2560_tx_intr(struct rt2560_softc *sc) DPRINTFN(sc, 9, "data frame sent after %u retries\n", retrycnt); if (data->rix != IEEE80211_FIXED_RATE_NONE) - ieee80211_amrr_tx_complete(&rn->amrr, - IEEE80211_AMRR_SUCCESS, retrycnt); + ieee80211_ratectl_tx_complete(vap, ni, + IEEE80211_RATECTL_TX_SUCCESS, + &retrycnt, NULL); ifp->if_opackets++; break; @@ -1002,8 +987,9 @@ rt2560_tx_intr(struct rt2560_softc *sc) DPRINTFN(sc, 9, "data frame failed after %d retries\n", retrycnt); if (data->rix != IEEE80211_FIXED_RATE_NONE) - ieee80211_amrr_tx_complete(&rn->amrr, - IEEE80211_AMRR_FAILURE, retrycnt); + ieee80211_ratectl_tx_complete(vap, ni, + IEEE80211_RATECTL_TX_FAILURE, + &retrycnt, NULL); ifp->if_oerrors++; break; @@ -1821,7 +1807,7 @@ rt2560_tx_data(struct rt2560_softc *sc, struct mbuf *m0, } else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE) { rate = tp->ucastrate; } else { - (void) ieee80211_amrr_choose(ni, &RT2560_NODE(ni)->amrr); + (void) ieee80211_ratectl_rate(ni, NULL, 0); rate = ni->ni_txrate; } diff --git a/sys/dev/ral/rt2560var.h b/sys/dev/ral/rt2560var.h index 288577b..b6a8d68 100644 --- a/sys/dev/ral/rt2560var.h +++ b/sys/dev/ral/rt2560var.h @@ -95,16 +95,9 @@ struct rt2560_rx_ring { int cur_decrypt; }; -struct rt2560_node { - struct ieee80211_node ni; - struct ieee80211_amrr_node amrr; -}; -#define RT2560_NODE(ni) ((struct rt2560_node *)(ni)) - struct rt2560_vap { struct ieee80211vap ral_vap; struct ieee80211_beacon_offsets ral_bo; - struct ieee80211_amrr amrr; int (*ral_newstate)(struct ieee80211vap *, enum ieee80211_state, int); diff --git a/sys/dev/ral/rt2661.c b/sys/dev/ral/rt2661.c index 9e6693f..9bc8838 100644 --- a/sys/dev/ral/rt2661.c +++ b/sys/dev/ral/rt2661.c @@ -55,7 +55,7 @@ __FBSDID("$FreeBSD$"); #include <net80211/ieee80211_var.h> #include <net80211/ieee80211_radiotap.h> #include <net80211/ieee80211_regdomain.h> -#include <net80211/ieee80211_amrr.h> +#include <net80211/ieee80211_ratectl.h> #include <netinet/in.h> #include <netinet/in_systm.h> @@ -100,8 +100,6 @@ static void rt2661_reset_rx_ring(struct rt2661_softc *, struct rt2661_rx_ring *); static void rt2661_free_rx_ring(struct rt2661_softc *, struct rt2661_rx_ring *); -static struct ieee80211_node *rt2661_node_alloc(struct ieee80211vap *, - const uint8_t [IEEE80211_ADDR_LEN]); static void rt2661_newassoc(struct ieee80211_node *, int); static int rt2661_newstate(struct ieee80211vap *, enum ieee80211_state, int); @@ -307,7 +305,6 @@ rt2661_attach(device_t dev, int id) ieee80211_ifattach(ic, macaddr); ic->ic_newassoc = rt2661_newassoc; - ic->ic_node_alloc = rt2661_node_alloc; #if 0 ic->ic_wme.wme_update = rt2661_wme_update; #endif @@ -428,11 +425,7 @@ rt2661_vap_create(struct ieee80211com *ic, vap->iv_update_beacon = rt2661_beacon_update; #endif - ieee80211_amrr_init(&rvp->amrr, vap, - IEEE80211_AMRR_MIN_SUCCESS_THRESHOLD, - IEEE80211_AMRR_MAX_SUCCESS_THRESHOLD, - 500 /* ms */); - + ieee80211_ratectl_init(vap); /* complete setup */ ieee80211_vap_attach(vap, ieee80211_media_change, ieee80211_media_status); if (TAILQ_FIRST(&ic->ic_vaps) == vap) @@ -445,7 +438,7 @@ rt2661_vap_delete(struct ieee80211vap *vap) { struct rt2661_vap *rvp = RT2661_VAP(vap); - ieee80211_amrr_cleanup(&rvp->amrr); + ieee80211_ratectl_deinit(vap); ieee80211_vap_detach(vap); free(rvp, M_80211_VAP); } @@ -771,25 +764,11 @@ rt2661_free_rx_ring(struct rt2661_softc *sc, struct rt2661_rx_ring *ring) bus_dma_tag_destroy(ring->data_dmat); } -static struct ieee80211_node * -rt2661_node_alloc(struct ieee80211vap *vap, - const uint8_t mac[IEEE80211_ADDR_LEN]) -{ - struct rt2661_node *rn; - - rn = malloc(sizeof (struct rt2661_node), M_80211_NODE, - M_NOWAIT | M_ZERO); - - return (rn != NULL) ? &rn->ni : NULL; -} - static void rt2661_newassoc(struct ieee80211_node *ni, int isnew) { - struct ieee80211vap *vap = ni->ni_vap; - - ieee80211_amrr_node_init(&RT2661_VAP(vap)->amrr, - &RT2661_NODE(ni)->amrr, ni); + /* XXX move */ + ieee80211_ratectl_node_init(ni); } static int @@ -899,9 +878,9 @@ rt2661_tx_intr(struct rt2661_softc *sc) struct ifnet *ifp = sc->sc_ifp; struct rt2661_tx_ring *txq; struct rt2661_tx_data *data; - struct rt2661_node *rn; uint32_t val; int qid, retrycnt; + struct ieee80211vap *vap; for (;;) { struct ieee80211_node *ni; @@ -925,8 +904,8 @@ rt2661_tx_intr(struct rt2661_softc *sc) /* if no frame has been sent, ignore */ if (ni == NULL) continue; - - rn = RT2661_NODE(ni); + else + vap = ni->ni_vap; switch (RT2661_TX_RESULT(val)) { case RT2661_TX_SUCCESS: @@ -935,8 +914,9 @@ rt2661_tx_intr(struct rt2661_softc *sc) DPRINTFN(sc, 10, "data frame sent successfully after " "%d retries\n", retrycnt); if (data->rix != IEEE80211_FIXED_RATE_NONE) - ieee80211_amrr_tx_complete(&rn->amrr, - IEEE80211_AMRR_SUCCESS, retrycnt); + ieee80211_ratectl_tx_complete(vap, ni, + IEEE80211_RATECTL_TX_SUCCESS, + &retrycnt, NULL); ifp->if_opackets++; break; @@ -946,8 +926,9 @@ rt2661_tx_intr(struct rt2661_softc *sc) DPRINTFN(sc, 9, "%s\n", "sending data frame failed (too much retries)"); if (data->rix != IEEE80211_FIXED_RATE_NONE) - ieee80211_amrr_tx_complete(&rn->amrr, - IEEE80211_AMRR_FAILURE, retrycnt); + ieee80211_ratectl_tx_complete(vap, ni, + IEEE80211_RATECTL_TX_FAILURE, + &retrycnt, NULL); ifp->if_oerrors++; break; @@ -1511,7 +1492,7 @@ rt2661_tx_data(struct rt2661_softc *sc, struct mbuf *m0, } else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE) { rate = tp->ucastrate; } else { - (void) ieee80211_amrr_choose(ni, &RT2661_NODE(ni)->amrr); + (void) ieee80211_ratectl_rate(ni, NULL, 0); rate = ni->ni_txrate; } rate &= IEEE80211_RATE_VAL; diff --git a/sys/dev/ral/rt2661var.h b/sys/dev/ral/rt2661var.h index db1d4de..9927d13 100644 --- a/sys/dev/ral/rt2661var.h +++ b/sys/dev/ral/rt2661var.h @@ -88,15 +88,8 @@ struct rt2661_rx_ring { int next; }; -struct rt2661_node { - struct ieee80211_node ni; - struct ieee80211_amrr_node amrr; -}; -#define RT2661_NODE(ni) ((struct rt2661_node *)(ni)) - struct rt2661_vap { struct ieee80211vap ral_vap; - struct ieee80211_amrr amrr; int (*ral_newstate)(struct ieee80211vap *, enum ieee80211_state, int); diff --git a/sys/dev/usb/wlan/if_rum.c b/sys/dev/usb/wlan/if_rum.c index da00489..4a5fbae 100644 --- a/sys/dev/usb/wlan/if_rum.c +++ b/sys/dev/usb/wlan/if_rum.c @@ -64,7 +64,7 @@ __FBSDID("$FreeBSD$"); #include <net80211/ieee80211_var.h> #include <net80211/ieee80211_regdomain.h> #include <net80211/ieee80211_radiotap.h> -#include <net80211/ieee80211_amrr.h> +#include <net80211/ieee80211_ratectl.h> #include <dev/usb/usb.h> #include <dev/usb/usbdi.h> @@ -140,7 +140,6 @@ static const struct usb_device_id rum_devs[] = { }; MODULE_DEPEND(rum, wlan, 1, 1, 1); -MODULE_DEPEND(rum, wlan_amrr, 1, 1, 1); MODULE_DEPEND(rum, usb, 1, 1, 1); static device_probe_t rum_match; @@ -212,17 +211,14 @@ static int rum_prepare_beacon(struct rum_softc *, struct ieee80211vap *); static int rum_raw_xmit(struct ieee80211_node *, struct mbuf *, const struct ieee80211_bpf_params *); -static struct ieee80211_node *rum_node_alloc(struct ieee80211vap *, - const uint8_t mac[IEEE80211_ADDR_LEN]); -static void rum_newassoc(struct ieee80211_node *, int); static void rum_scan_start(struct ieee80211com *); static void rum_scan_end(struct ieee80211com *); static void rum_set_channel(struct ieee80211com *); static int rum_get_rssi(struct rum_softc *, uint8_t); -static void rum_amrr_start(struct rum_softc *, +static void rum_ratectl_start(struct rum_softc *, struct ieee80211_node *); -static void rum_amrr_timeout(void *); -static void rum_amrr_task(void *, int); +static void rum_ratectl_timeout(void *); +static void rum_ratectl_task(void *, int); static int rum_pause(struct rum_softc *, int); static const struct { @@ -511,9 +507,7 @@ rum_attach(device_t self) ieee80211_ifattach(ic, sc->sc_bssid); ic->ic_update_promisc = rum_update_promisc; - ic->ic_newassoc = rum_newassoc; ic->ic_raw_xmit = rum_raw_xmit; - ic->ic_node_alloc = rum_node_alloc; ic->ic_scan_start = rum_scan_start; ic->ic_scan_end = rum_scan_end; ic->ic_set_channel = rum_set_channel; @@ -608,13 +602,10 @@ rum_vap_create(struct ieee80211com *ic, rvp->newstate = vap->iv_newstate; vap->iv_newstate = rum_newstate; - usb_callout_init_mtx(&rvp->amrr_ch, &sc->sc_mtx, 0); - TASK_INIT(&rvp->amrr_task, 0, rum_amrr_task, rvp); - ieee80211_amrr_init(&rvp->amrr, vap, - IEEE80211_AMRR_MIN_SUCCESS_THRESHOLD, - IEEE80211_AMRR_MAX_SUCCESS_THRESHOLD, - 1000 /* 1 sec */); - + usb_callout_init_mtx(&rvp->ratectl_ch, &sc->sc_mtx, 0); + TASK_INIT(&rvp->ratectl_task, 0, rum_ratectl_task, rvp); + ieee80211_ratectl_init(vap); + ieee80211_ratectl_setinterval(vap, 1000 /* 1 sec */); /* complete setup */ ieee80211_vap_attach(vap, ieee80211_media_change, ieee80211_media_status); ic->ic_opmode = opmode; @@ -627,9 +618,9 @@ rum_vap_delete(struct ieee80211vap *vap) struct rum_vap *rvp = RUM_VAP(vap); struct ieee80211com *ic = vap->iv_ic; - usb_callout_drain(&rvp->amrr_ch); - ieee80211_draintask(ic, &rvp->amrr_task); - ieee80211_amrr_cleanup(&rvp->amrr); + usb_callout_drain(&rvp->ratectl_ch); + ieee80211_draintask(ic, &rvp->ratectl_task); + ieee80211_ratectl_deinit(vap); ieee80211_vap_detach(vap); free(rvp, M_80211_VAP); } @@ -716,7 +707,7 @@ rum_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) IEEE80211_UNLOCK(ic); RUM_LOCK(sc); - usb_callout_stop(&rvp->amrr_ch); + usb_callout_stop(&rvp->ratectl_ch); switch (nstate) { case IEEE80211_S_INIT: @@ -751,7 +742,7 @@ rum_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) /* enable automatic rate adaptation */ tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)]; if (tp->ucastrate == IEEE80211_FIXED_RATE_NONE) - rum_amrr_start(sc, ni); + rum_ratectl_start(sc, ni); break; default: break; @@ -2194,7 +2185,7 @@ bad: } static void -rum_amrr_start(struct rum_softc *sc, struct ieee80211_node *ni) +rum_ratectl_start(struct rum_softc *sc, struct ieee80211_node *ni) { struct ieee80211vap *vap = ni->ni_vap; struct rum_vap *rvp = RUM_VAP(vap); @@ -2202,23 +2193,23 @@ rum_amrr_start(struct rum_softc *sc, struct ieee80211_node *ni) /* clear statistic registers (STA_CSR0 to STA_CSR5) */ rum_read_multi(sc, RT2573_STA_CSR0, sc->sta, sizeof sc->sta); - ieee80211_amrr_node_init(&rvp->amrr, &RUM_NODE(ni)->amn, ni); + ieee80211_ratectl_node_init(ni); - usb_callout_reset(&rvp->amrr_ch, hz, rum_amrr_timeout, rvp); + usb_callout_reset(&rvp->ratectl_ch, hz, rum_ratectl_timeout, rvp); } static void -rum_amrr_timeout(void *arg) +rum_ratectl_timeout(void *arg) { struct rum_vap *rvp = arg; struct ieee80211vap *vap = &rvp->vap; struct ieee80211com *ic = vap->iv_ic; - ieee80211_runtask(ic, &rvp->amrr_task); + ieee80211_runtask(ic, &rvp->ratectl_task); } static void -rum_amrr_task(void *arg, int pending) +rum_ratectl_task(void *arg, int pending) { struct rum_vap *rvp = arg; struct ieee80211vap *vap = &rvp->vap; @@ -2227,6 +2218,7 @@ rum_amrr_task(void *arg, int pending) struct rum_softc *sc = ifp->if_softc; struct ieee80211_node *ni = vap->iv_bss; int ok, fail; + int sum, retrycnt; RUM_LOCK(sc); /* read and clear statistic registers (STA_CSR0 to STA_CSR10) */ @@ -2235,36 +2227,18 @@ rum_amrr_task(void *arg, int pending) ok = (le32toh(sc->sta[4]) >> 16) + /* TX ok w/o retry */ (le32toh(sc->sta[5]) & 0xffff); /* TX ok w/ retry */ fail = (le32toh(sc->sta[5]) >> 16); /* TX retry-fail count */ + sum = ok+fail; + retrycnt = (le32toh(sc->sta[5]) & 0xffff) + fail; - ieee80211_amrr_tx_update(&RUM_NODE(ni)->amn, - ok+fail, ok, (le32toh(sc->sta[5]) & 0xffff) + fail); - (void) ieee80211_amrr_choose(ni, &RUM_NODE(ni)->amn); + ieee80211_ratectl_tx_update(vap, ni, &sum, &ok, &retrycnt); + (void) ieee80211_ratectl_rate(ni, NULL, 0); ifp->if_oerrors += fail; /* count TX retry-fail as Tx errors */ - usb_callout_reset(&rvp->amrr_ch, hz, rum_amrr_timeout, rvp); + usb_callout_reset(&rvp->ratectl_ch, hz, rum_ratectl_timeout, rvp); RUM_UNLOCK(sc); } -/* ARGUSED */ -static struct ieee80211_node * -rum_node_alloc(struct ieee80211vap *vap __unused, - const uint8_t mac[IEEE80211_ADDR_LEN] __unused) -{ - struct rum_node *rn; - - rn = malloc(sizeof(struct rum_node), M_80211_NODE, M_NOWAIT | M_ZERO); - return rn != NULL ? &rn->ni : NULL; -} - -static void -rum_newassoc(struct ieee80211_node *ni, int isnew) -{ - struct ieee80211vap *vap = ni->ni_vap; - - ieee80211_amrr_node_init(&RUM_VAP(vap)->amrr, &RUM_NODE(ni)->amn, ni); -} - static void rum_scan_start(struct ieee80211com *ic) { diff --git a/sys/dev/usb/wlan/if_rumvar.h b/sys/dev/usb/wlan/if_rumvar.h index 82bb117..f46634c 100644 --- a/sys/dev/usb/wlan/if_rumvar.h +++ b/sys/dev/usb/wlan/if_rumvar.h @@ -67,18 +67,11 @@ struct rum_tx_data { }; typedef STAILQ_HEAD(, rum_tx_data) rum_txdhead; -struct rum_node { - struct ieee80211_node ni; - struct ieee80211_amrr_node amn; -}; -#define RUM_NODE(ni) ((struct rum_node *)(ni)) - struct rum_vap { struct ieee80211vap vap; struct ieee80211_beacon_offsets bo; - struct ieee80211_amrr amrr; - struct usb_callout amrr_ch; - struct task amrr_task; + struct usb_callout ratectl_ch; + struct task ratectl_task; int (*newstate)(struct ieee80211vap *, enum ieee80211_state, int); diff --git a/sys/dev/usb/wlan/if_run.c b/sys/dev/usb/wlan/if_run.c index df53560..3ab607f 100644 --- a/sys/dev/usb/wlan/if_run.c +++ b/sys/dev/usb/wlan/if_run.c @@ -65,7 +65,7 @@ __FBSDID("$FreeBSD$"); #include <net80211/ieee80211_var.h> #include <net80211/ieee80211_regdomain.h> #include <net80211/ieee80211_radiotap.h> -#include <net80211/ieee80211_amrr.h> +#include <net80211/ieee80211_ratectl.h> #include <dev/usb/usb.h> #include <dev/usb/usbdi.h> @@ -290,7 +290,6 @@ static const struct usb_device_id run_devs[] = { }; MODULE_DEPEND(run, wlan, 1, 1, 1); -MODULE_DEPEND(run, wlan_amrr, 1, 1, 1); MODULE_DEPEND(run, usb, 1, 1, 1); MODULE_DEPEND(run, firmware, 1, 1, 1); @@ -350,9 +349,9 @@ static int run_key_set(struct ieee80211vap *, const struct ieee80211_key *, const uint8_t mac[IEEE80211_ADDR_LEN]); static int run_key_delete(struct ieee80211vap *, const struct ieee80211_key *); -static void run_amrr_start(struct run_softc *, struct ieee80211_node *); -static void run_amrr_to(void *); -static void run_amrr_cb(void *, int); +static void run_ratectl_start(struct run_softc *, struct ieee80211_node *); +static void run_ratectl_to(void *); +static void run_ratectl_cb(void *, int); static void run_iter_func(void *, struct ieee80211_node *); static void run_newassoc(struct ieee80211_node *, int); static void run_rx_frame(struct run_softc *, struct mbuf *, uint32_t); @@ -754,14 +753,12 @@ run_vap_create(struct ieee80211com *ic, rvp->newstate = vap->iv_newstate; vap->iv_newstate = run_newstate; - TASK_INIT(&rvp->amrr_task, 0, run_amrr_cb, rvp); + TASK_INIT(&rvp->ratectl_task, 0, run_ratectl_cb, rvp); TASK_INIT(&sc->wme_task, 0, run_wme_update_cb, ic); TASK_INIT(&sc->usb_timeout_task, 0, run_usb_timeout_cb, sc); - callout_init((struct callout *)&rvp->amrr_ch, 1); - ieee80211_amrr_init(&rvp->amrr, vap, - IEEE80211_AMRR_MIN_SUCCESS_THRESHOLD, - IEEE80211_AMRR_MAX_SUCCESS_THRESHOLD, - 1000 /* 1 sec */); + callout_init((struct callout *)&rvp->ratectl_ch, 1); + ieee80211_ratectl_init(vap); + ieee80211_ratectl_setinterval(vap, 1000 /* 1 sec */); /* complete setup */ ieee80211_vap_attach(vap, run_media_change, ieee80211_media_status); @@ -786,16 +783,16 @@ run_vap_delete(struct ieee80211vap *vap) sc = ifp->if_softc; RUN_LOCK(sc); - sc->sc_rvp->amrr_run = RUN_AMRR_OFF; + sc->sc_rvp->ratectl_run = RUN_RATECTL_OFF; RUN_UNLOCK(sc); /* drain them all */ - usb_callout_drain(&sc->sc_rvp->amrr_ch); - ieee80211_draintask(ic, &sc->sc_rvp->amrr_task); + usb_callout_drain(&sc->sc_rvp->ratectl_ch); + ieee80211_draintask(ic, &sc->sc_rvp->ratectl_task); ieee80211_draintask(ic, &sc->wme_task); ieee80211_draintask(ic, &sc->usb_timeout_task); - ieee80211_amrr_cleanup(&rvp->amrr); + ieee80211_ratectl_deinit(vap); ieee80211_vap_detach(vap); free(rvp, M_80211_VAP); sc->sc_rvp = NULL; @@ -1632,8 +1629,8 @@ run_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) IEEE80211_UNLOCK(ic); RUN_LOCK(sc); - sc->sc_rvp->amrr_run = RUN_AMRR_OFF; - usb_callout_stop(&rvp->amrr_ch); + sc->sc_rvp->ratectl_run = RUN_RATECTL_OFF; + usb_callout_stop(&rvp->ratectl_ch); if (ostate == IEEE80211_S_RUN) { /* turn link LED off */ @@ -1681,7 +1678,7 @@ run_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) /* enable automatic rate adaptation */ tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)]; if (tp->ucastrate == IEEE80211_FIXED_RATE_NONE) - run_amrr_start(sc, ni); + run_ratectl_start(sc, ni); /* turn link LED on */ run_set_leds(sc, RT2860_LED_RADIO | @@ -1961,12 +1958,11 @@ fail: } static void -run_amrr_start(struct run_softc *sc, struct ieee80211_node *ni) +run_ratectl_start(struct run_softc *sc, struct ieee80211_node *ni) { struct ieee80211vap *vap = ni->ni_vap; struct run_vap *rvp = RUN_VAP(vap); uint32_t sta[3]; - uint8_t wcid; RUN_LOCK_ASSERT(sc, MA_OWNED); @@ -1974,30 +1970,29 @@ run_amrr_start(struct run_softc *sc, struct ieee80211_node *ni) run_read_region_1(sc, RT2860_TX_STA_CNT0, (uint8_t *)sta, sizeof sta); - wcid = RUN_AID2WCID(ni == NULL ? 0 : ni->ni_associd); - ieee80211_amrr_node_init(&rvp->amrr, &rvp->amn[wcid], ni); + ieee80211_ratectl_node_init(ni); /* start at lowest available bit-rate, AMRR will raise */ ni->ni_txrate = 2; /* start calibration timer */ - rvp->amrr_run = RUN_AMRR_ON; - usb_callout_reset(&rvp->amrr_ch, hz, run_amrr_to, rvp); + rvp->ratectl_run = RUN_RATECTL_ON; + usb_callout_reset(&rvp->ratectl_ch, hz, run_ratectl_to, rvp); } static void -run_amrr_to(void *arg) +run_ratectl_to(void *arg) { struct run_vap *rvp = arg; /* do it in a process context, so it can go sleep */ - ieee80211_runtask(rvp->vap.iv_ic, &rvp->amrr_task); + ieee80211_runtask(rvp->vap.iv_ic, &rvp->ratectl_task); /* next timeout will be rescheduled in the callback task */ } /* ARGSUSED */ static void -run_amrr_cb(void *arg, int pending) +run_ratectl_cb(void *arg, int pending) { struct run_vap *rvp = arg; struct ieee80211vap *vap = &rvp->vap; @@ -2020,8 +2015,8 @@ run_amrr_cb(void *arg, int pending) ieee80211_iterate_nodes(&ic->ic_sta, run_iter_func, rvp); } - if(rvp->amrr_run == RUN_AMRR_ON) - usb_callout_reset(&rvp->amrr_ch, hz, run_amrr_to, rvp); + if(rvp->ratectl_run == RUN_RATECTL_ON) + usb_callout_reset(&rvp->ratectl_ch, hz, run_ratectl_to, rvp); } @@ -2033,10 +2028,11 @@ run_iter_func(void *arg, struct ieee80211_node *ni) struct ifnet *ifp = ic->ic_ifp; struct run_softc *sc = ifp->if_softc; struct ieee80211_node_table *nt = &ic->ic_sta; - struct ieee80211_amrr_node *amn = &rvp->amn[0]; /* make compiler happy */ uint32_t sta[3], stat; int error; uint8_t wcid, mcs, pid; + struct ieee80211vap *vap = ni->ni_vap; + int txcnt = 0, success = 0, retrycnt = 0; if(ic->ic_opmode != IEEE80211_M_STA) IEEE80211_NODE_ITERATE_UNLOCK(nt); @@ -2056,10 +2052,7 @@ run_iter_func(void *arg, struct ieee80211_node *ni) continue; /* update per-STA AMRR stats */ - amn = &rvp->amn[wcid]; - amn->amn_txcnt++; if (stat & RT2860_TXQ_OK) { - amn->amn_success++; /* * Check if there were retries, ie if the Tx * success rate is different from the requested @@ -2069,16 +2062,20 @@ run_iter_func(void *arg, struct ieee80211_node *ni) mcs = (stat >> RT2860_TXQ_MCS_SHIFT) & 0x7f; pid = (stat >> RT2860_TXQ_PID_SHIFT) & 0xf; if (mcs + 1 != pid) - amn->amn_retrycnt++; + retrycnt = 1; + ieee80211_ratectl_tx_complete(vap, ni, + IEEE80211_RATECTL_TX_SUCCESS, + &retrycnt, NULL); } else { - amn->amn_retrycnt++; + retrycnt = 1; + ieee80211_ratectl_tx_complete(vap, ni, + IEEE80211_RATECTL_TX_SUCCESS, + &retrycnt, NULL); ifp->if_oerrors++; } run_read_region_1(sc, RT2860_TX_STAT_FIFO, (uint8_t *)&stat, sizeof stat); } - DPRINTFN(3, "retrycnt=%d txcnt=%d success=%d\n", - amn->amn_retrycnt, amn->amn_txcnt, amn->amn_success); } else { /* read statistic counters (clear on read) and update AMRR state */ error = run_read_region_1(sc, RT2860_TX_STA_CNT0, (uint8_t *)sta, @@ -2090,26 +2087,25 @@ run_iter_func(void *arg, struct ieee80211_node *ni) le32toh(sta[1]) >> 16, le32toh(sta[1]) & 0xffff, le32toh(sta[0]) & 0xffff); - wcid = RUN_AID2WCID(ni == NULL ? 0 : ni->ni_associd); - amn = &rvp->amn[wcid]; - /* count failed TX as errors */ ifp->if_oerrors += le32toh(sta[0]) & 0xffff; - amn->amn_retrycnt = + retrycnt = (le32toh(sta[0]) & 0xffff) + /* failed TX count */ (le32toh(sta[1]) >> 16); /* TX retransmission count */ - amn->amn_txcnt = - amn->amn_retrycnt + + txcnt = + retrycnt + (le32toh(sta[1]) & 0xffff); /* successful TX count */ - amn->amn_success = + success = (le32toh(sta[1]) >> 16) + (le32toh(sta[1]) & 0xffff); + ieee80211_ratectl_tx_update(vap, ni, &txcnt, &success, + &retrycnt); } - ieee80211_amrr_choose(ni, amn); + ieee80211_ratectl_rate(ni, NULL, 0); skip:; RUN_UNLOCK(sc); @@ -4447,7 +4443,7 @@ run_stop(void *arg) RUN_LOCK_ASSERT(sc, MA_OWNED); if(sc->sc_rvp != NULL){ - sc->sc_rvp->amrr_run = RUN_AMRR_OFF; + sc->sc_rvp->ratectl_run = RUN_RATECTL_OFF; if (ic->ic_flags & IEEE80211_F_SCAN) ieee80211_cancel_scan(&sc->sc_rvp->vap); } diff --git a/sys/dev/usb/wlan/if_runvar.h b/sys/dev/usb/wlan/if_runvar.h index 87b15bc..a7f8f1f 100644 --- a/sys/dev/usb/wlan/if_runvar.h +++ b/sys/dev/usb/wlan/if_runvar.h @@ -107,13 +107,11 @@ struct run_node { struct run_vap { struct ieee80211vap vap; struct ieee80211_beacon_offsets bo; - struct ieee80211_amrr amrr; - struct ieee80211_amrr_node amn[RT2870_WCID_MAX + 1]; - struct usb_callout amrr_ch; - struct task amrr_task; - uint8_t amrr_run; -#define RUN_AMRR_ON 1 -#define RUN_AMRR_OFF 0 + struct usb_callout ratectl_ch; + struct task ratectl_task; + uint8_t ratectl_run; +#define RUN_RATECTL_ON 1 +#define RUN_RATECTL_OFF 0 int (*newstate)(struct ieee80211vap *, enum ieee80211_state, int); diff --git a/sys/dev/usb/wlan/if_ural.c b/sys/dev/usb/wlan/if_ural.c index 4d97e7a..4a4378b 100644 --- a/sys/dev/usb/wlan/if_ural.c +++ b/sys/dev/usb/wlan/if_ural.c @@ -66,7 +66,7 @@ __FBSDID("$FreeBSD$"); #include <net80211/ieee80211_var.h> #include <net80211/ieee80211_regdomain.h> #include <net80211/ieee80211_radiotap.h> -#include <net80211/ieee80211_amrr.h> +#include <net80211/ieee80211_ratectl.h> #include <dev/usb/usb.h> #include <dev/usb/usbdi.h> @@ -162,9 +162,6 @@ static void ural_write_multi(struct ural_softc *, uint16_t, void *, static void ural_bbp_write(struct ural_softc *, uint8_t, uint8_t); static uint8_t ural_bbp_read(struct ural_softc *, uint8_t); static void ural_rf_write(struct ural_softc *, uint8_t, uint32_t); -static struct ieee80211_node *ural_node_alloc(struct ieee80211vap *, - const uint8_t mac[IEEE80211_ADDR_LEN]); -static void ural_newassoc(struct ieee80211_node *, int); static void ural_scan_start(struct ieee80211com *); static void ural_scan_end(struct ieee80211com *); static void ural_set_channel(struct ieee80211com *); @@ -191,10 +188,10 @@ static void ural_init(void *); static void ural_stop(struct ural_softc *); static int ural_raw_xmit(struct ieee80211_node *, struct mbuf *, const struct ieee80211_bpf_params *); -static void ural_amrr_start(struct ural_softc *, +static void ural_ratectl_start(struct ural_softc *, struct ieee80211_node *); -static void ural_amrr_timeout(void *); -static void ural_amrr_task(void *, int); +static void ural_ratectl_timeout(void *); +static void ural_ratectl_task(void *, int); static int ural_pause(struct ural_softc *sc, int timeout); /* @@ -403,7 +400,6 @@ static devclass_t ural_devclass; DRIVER_MODULE(ural, uhub, ural_driver, ural_devclass, NULL, 0); MODULE_DEPEND(ural, usb, 1, 1, 1); MODULE_DEPEND(ural, wlan, 1, 1, 1); -MODULE_DEPEND(ural, wlan_amrr, 1, 1, 1); static int ural_match(device_t self) @@ -500,9 +496,7 @@ ural_attach(device_t self) ieee80211_ifattach(ic, sc->sc_bssid); ic->ic_update_promisc = ural_update_promisc; - ic->ic_newassoc = ural_newassoc; ic->ic_raw_xmit = ural_raw_xmit; - ic->ic_node_alloc = ural_node_alloc; ic->ic_scan_start = ural_scan_start; ic->ic_scan_end = ural_scan_end; ic->ic_set_channel = ural_set_channel; @@ -597,12 +591,10 @@ ural_vap_create(struct ieee80211com *ic, uvp->newstate = vap->iv_newstate; vap->iv_newstate = ural_newstate; - usb_callout_init_mtx(&uvp->amrr_ch, &sc->sc_mtx, 0); - TASK_INIT(&uvp->amrr_task, 0, ural_amrr_task, uvp); - ieee80211_amrr_init(&uvp->amrr, vap, - IEEE80211_AMRR_MIN_SUCCESS_THRESHOLD, - IEEE80211_AMRR_MAX_SUCCESS_THRESHOLD, - 1000 /* 1 sec */); + usb_callout_init_mtx(&uvp->ratectl_ch, &sc->sc_mtx, 0); + TASK_INIT(&uvp->ratectl_task, 0, ural_ratectl_task, uvp); + ieee80211_ratectl_init(vap); + ieee80211_ratectl_setinterval(vap, 1000 /* 1 sec */); /* complete setup */ ieee80211_vap_attach(vap, ieee80211_media_change, ieee80211_media_status); @@ -616,9 +608,9 @@ ural_vap_delete(struct ieee80211vap *vap) struct ural_vap *uvp = URAL_VAP(vap); struct ieee80211com *ic = vap->iv_ic; - usb_callout_drain(&uvp->amrr_ch); - ieee80211_draintask(ic, &uvp->amrr_task); - ieee80211_amrr_cleanup(&uvp->amrr); + usb_callout_drain(&uvp->ratectl_ch); + ieee80211_draintask(ic, &uvp->ratectl_task); + ieee80211_ratectl_deinit(vap); ieee80211_vap_detach(vap); free(uvp, M_80211_VAP); } @@ -703,7 +695,7 @@ ural_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) IEEE80211_UNLOCK(ic); RAL_LOCK(sc); - usb_callout_stop(&uvp->amrr_ch); + usb_callout_stop(&uvp->ratectl_ch); switch (nstate) { case IEEE80211_S_INIT: @@ -759,7 +751,7 @@ ural_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) /* XXX should use ic_bsschan but not valid until after newstate call below */ tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)]; if (tp->ucastrate == IEEE80211_FIXED_RATE_NONE) - ural_amrr_start(sc, ni); + ural_ratectl_start(sc, ni); break; @@ -1584,25 +1576,6 @@ ural_rf_write(struct ural_softc *sc, uint8_t reg, uint32_t val) DPRINTFN(15, "RF R[%u] <- 0x%05x\n", reg & 0x3, val & 0xfffff); } -/* ARGUSED */ -static struct ieee80211_node * -ural_node_alloc(struct ieee80211vap *vap __unused, - const uint8_t mac[IEEE80211_ADDR_LEN] __unused) -{ - struct ural_node *un; - - un = malloc(sizeof(struct ural_node), M_80211_NODE, M_NOWAIT | M_ZERO); - return un != NULL ? &un->ni : NULL; -} - -static void -ural_newassoc(struct ieee80211_node *ni, int isnew) -{ - struct ieee80211vap *vap = ni->ni_vap; - - ieee80211_amrr_node_init(&URAL_VAP(vap)->amrr, &URAL_NODE(ni)->amn, ni); -} - static void ural_scan_start(struct ieee80211com *ic) { @@ -2231,7 +2204,7 @@ bad: } static void -ural_amrr_start(struct ural_softc *sc, struct ieee80211_node *ni) +ural_ratectl_start(struct ural_softc *sc, struct ieee80211_node *ni) { struct ieee80211vap *vap = ni->ni_vap; struct ural_vap *uvp = URAL_VAP(vap); @@ -2239,23 +2212,23 @@ ural_amrr_start(struct ural_softc *sc, struct ieee80211_node *ni) /* clear statistic registers (STA_CSR0 to STA_CSR10) */ ural_read_multi(sc, RAL_STA_CSR0, sc->sta, sizeof sc->sta); - ieee80211_amrr_node_init(&uvp->amrr, &URAL_NODE(ni)->amn, ni); + ieee80211_ratectl_node_init(ni); - usb_callout_reset(&uvp->amrr_ch, hz, ural_amrr_timeout, uvp); + usb_callout_reset(&uvp->ratectl_ch, hz, ural_ratectl_timeout, uvp); } static void -ural_amrr_timeout(void *arg) +ural_ratectl_timeout(void *arg) { struct ural_vap *uvp = arg; struct ieee80211vap *vap = &uvp->vap; struct ieee80211com *ic = vap->iv_ic; - ieee80211_runtask(ic, &uvp->amrr_task); + ieee80211_runtask(ic, &uvp->ratectl_task); } static void -ural_amrr_task(void *arg, int pending) +ural_ratectl_task(void *arg, int pending) { struct ural_vap *uvp = arg; struct ieee80211vap *vap = &uvp->vap; @@ -2264,6 +2237,7 @@ ural_amrr_task(void *arg, int pending) struct ural_softc *sc = ifp->if_softc; struct ieee80211_node *ni = vap->iv_bss; int ok, fail; + int sum, retrycnt; RAL_LOCK(sc); /* read and clear statistic registers (STA_CSR0 to STA_CSR10) */ @@ -2272,14 +2246,15 @@ ural_amrr_task(void *arg, int pending) ok = sc->sta[7] + /* TX ok w/o retry */ sc->sta[8]; /* TX ok w/ retry */ fail = sc->sta[9]; /* TX retry-fail count */ + sum = ok+fail; + retrycnt = sc->sta[8] + fail; - ieee80211_amrr_tx_update(&URAL_NODE(ni)->amn, - ok+fail, ok, sc->sta[8] + fail); - (void) ieee80211_amrr_choose(ni, &URAL_NODE(ni)->amn); + ieee80211_ratectl_tx_update(vap, ni, &sum, &ok, &retrycnt); + (void) ieee80211_ratectl_rate(ni, NULL, 0); ifp->if_oerrors += fail; /* count TX retry-fail as Tx errors */ - usb_callout_reset(&uvp->amrr_ch, hz, ural_amrr_timeout, uvp); + usb_callout_reset(&uvp->ratectl_ch, hz, ural_ratectl_timeout, uvp); RAL_UNLOCK(sc); } diff --git a/sys/dev/usb/wlan/if_uralvar.h b/sys/dev/usb/wlan/if_uralvar.h index 5d9c582..46dbfbd 100644 --- a/sys/dev/usb/wlan/if_uralvar.h +++ b/sys/dev/usb/wlan/if_uralvar.h @@ -71,18 +71,11 @@ struct ural_tx_data { }; typedef STAILQ_HEAD(, ural_tx_data) ural_txdhead; -struct ural_node { - struct ieee80211_node ni; - struct ieee80211_amrr_node amn; -}; -#define URAL_NODE(ni) ((struct ural_node *)(ni)) - struct ural_vap { struct ieee80211vap vap; struct ieee80211_beacon_offsets bo; - struct ieee80211_amrr amrr; - struct usb_callout amrr_ch; - struct task amrr_task; + struct usb_callout ratectl_ch; + struct task ratectl_task; int (*newstate)(struct ieee80211vap *, enum ieee80211_state, int); diff --git a/sys/dev/usb/wlan/if_urtw.c b/sys/dev/usb/wlan/if_urtw.c index 6604268..2b20a62 100644 --- a/sys/dev/usb/wlan/if_urtw.c +++ b/sys/dev/usb/wlan/if_urtw.c @@ -62,6 +62,7 @@ __FBSDID("$FreeBSD$"); #include <dev/usb/wlan/if_urtwvar.h> SYSCTL_NODE(_hw_usb, OID_AUTO, urtw, CTLFLAG_RW, 0, "USB Realtek 8187L"); +#define URTW_DEBUG #ifdef URTW_DEBUG int urtw_debug = 0; SYSCTL_INT(_hw_usb_urtw, OID_AUTO, debug, CTLFLAG_RW, &urtw_debug, 0, diff --git a/sys/dev/usb/wlan/if_zyd.c b/sys/dev/usb/wlan/if_zyd.c index 96b8cf2..a0b8179 100644 --- a/sys/dev/usb/wlan/if_zyd.c +++ b/sys/dev/usb/wlan/if_zyd.c @@ -65,7 +65,7 @@ __FBSDID("$FreeBSD$"); #include <net80211/ieee80211_var.h> #include <net80211/ieee80211_regdomain.h> #include <net80211/ieee80211_radiotap.h> -#include <net80211/ieee80211_amrr.h> +#include <net80211/ieee80211_ratectl.h> #include <dev/usb/usb.h> #include <dev/usb/usbdi.h> @@ -125,8 +125,6 @@ static void zyd_vap_delete(struct ieee80211vap *); static void zyd_tx_free(struct zyd_tx_data *, int); static void zyd_setup_tx_list(struct zyd_softc *); static void zyd_unsetup_tx_list(struct zyd_softc *); -static struct ieee80211_node *zyd_node_alloc(struct ieee80211vap *, - const uint8_t mac[IEEE80211_ADDR_LEN]); static int zyd_newstate(struct ieee80211vap *, enum ieee80211_state, int); static int zyd_cmd(struct zyd_softc *, uint16_t, const void *, int, void *, int, int); @@ -163,7 +161,6 @@ static void zyd_init_locked(struct zyd_softc *); static void zyd_init(void *); static void zyd_stop(struct zyd_softc *); static int zyd_loadfirmware(struct zyd_softc *); -static void zyd_newassoc(struct ieee80211_node *, int); static void zyd_scan_start(struct ieee80211com *); static void zyd_scan_end(struct ieee80211com *); static void zyd_set_channel(struct ieee80211com *); @@ -408,9 +405,7 @@ zyd_attach(device_t dev) ieee80211_init_channels(ic, NULL, &bands); ieee80211_ifattach(ic, sc->sc_bssid); - ic->ic_newassoc = zyd_newassoc; ic->ic_raw_xmit = zyd_raw_xmit; - ic->ic_node_alloc = zyd_node_alloc; ic->ic_scan_start = zyd_scan_start; ic->ic_scan_end = zyd_scan_end; ic->ic_set_channel = zyd_set_channel; @@ -483,10 +478,8 @@ zyd_vap_create(struct ieee80211com *ic, zvp->newstate = vap->iv_newstate; vap->iv_newstate = zyd_newstate; - ieee80211_amrr_init(&zvp->amrr, vap, - IEEE80211_AMRR_MIN_SUCCESS_THRESHOLD, - IEEE80211_AMRR_MAX_SUCCESS_THRESHOLD, - 1000 /* 1 sec */); + ieee80211_ratectl_init(vap); + ieee80211_ratectl_setinterval(vap, 1000 /* 1 sec */); /* complete setup */ ieee80211_vap_attach(vap, ieee80211_media_change, @@ -500,7 +493,7 @@ zyd_vap_delete(struct ieee80211vap *vap) { struct zyd_vap *zvp = ZYD_VAP(vap); - ieee80211_amrr_cleanup(&zvp->amrr); + ieee80211_ratectl_deinit(vap); ieee80211_vap_detach(vap); free(zvp, M_80211_VAP); } @@ -518,8 +511,8 @@ zyd_tx_free(struct zyd_tx_data *data, int txerr) data->m = NULL; if (txerr == 0) - ieee80211_amrr_tx_complete(&ZYD_NODE(data->ni)->amn, - IEEE80211_AMRR_SUCCESS, 0); + ieee80211_ratectl_tx_complete(data->ni->ni_vap, + data->ni, IEEE80211_RATECTL_TX_SUCCESS, NULL, NULL); ieee80211_free_node(data->ni); data->ni = NULL; } @@ -572,17 +565,6 @@ zyd_unsetup_tx_list(struct zyd_softc *sc) } } -/* ARGUSED */ -static struct ieee80211_node * -zyd_node_alloc(struct ieee80211vap *vap __unused, - const uint8_t mac[IEEE80211_ADDR_LEN] __unused) -{ - struct zyd_node *zn; - - zn = malloc(sizeof(struct zyd_node), M_80211_NODE, M_NOWAIT | M_ZERO); - return (zn != NULL) ? (&zn->ni) : (NULL); -} - static int zyd_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) { @@ -669,9 +651,12 @@ zyd_intr_read_callback(struct usb_xfer *xfer, usb_error_t error) */ ni = ieee80211_find_txnode(vap, retry->macaddr); if (ni != NULL) { - ieee80211_amrr_tx_complete(&ZYD_NODE(ni)->amn, - IEEE80211_AMRR_FAILURE, - (int)(le16toh(retry->count) & 0xff)); + int retrycnt = + (int)(le16toh(retry->count) & 0xff); + + ieee80211_ratectl_tx_complete(vap, ni, + IEEE80211_RATECTL_TX_FAILURE, + &retrycnt, NULL); ieee80211_free_node(ni); } if (le16toh(retry->count) & 0x100) @@ -2498,7 +2483,7 @@ zyd_tx_start(struct zyd_softc *sc, struct mbuf *m0, struct ieee80211_node *ni) else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE) rate = tp->ucastrate; else { - (void) ieee80211_amrr_choose(ni, &ZYD_NODE(ni)->amn); + (void) ieee80211_ratectl_rate(ni, NULL, 0); rate = ni->ni_txrate; } } @@ -2910,14 +2895,6 @@ zyd_loadfirmware(struct zyd_softc *sc) } static void -zyd_newassoc(struct ieee80211_node *ni, int isnew) -{ - struct ieee80211vap *vap = ni->ni_vap; - - ieee80211_amrr_node_init(&ZYD_VAP(vap)->amrr, &ZYD_NODE(ni)->amn, ni); -} - -static void zyd_scan_start(struct ieee80211com *ic) { struct ifnet *ifp = ic->ic_ifp; @@ -2970,4 +2947,3 @@ static devclass_t zyd_devclass; DRIVER_MODULE(zyd, uhub, zyd_driver, zyd_devclass, NULL, 0); MODULE_DEPEND(zyd, usb, 1, 1, 1); MODULE_DEPEND(zyd, wlan, 1, 1, 1); -MODULE_DEPEND(zyd, wlan_amrr, 1, 1, 1); diff --git a/sys/dev/usb/wlan/if_zydreg.h b/sys/dev/usb/wlan/if_zydreg.h index 57a5e87..dd11632 100644 --- a/sys/dev/usb/wlan/if_zydreg.h +++ b/sys/dev/usb/wlan/if_zydreg.h @@ -1177,12 +1177,6 @@ struct zyd_rx_data { int rssi; }; -struct zyd_node { - struct ieee80211_node ni; /* must be the first */ - struct ieee80211_amrr_node amn; -}; -#define ZYD_NODE(ni) ((struct zyd_node *)(ni)) - struct zyd_rx_radiotap_header { struct ieee80211_radiotap_header wr_ihdr; uint8_t wr_flags; @@ -1243,7 +1237,6 @@ struct zyd_vap { struct ieee80211vap vap; int (*newstate)(struct ieee80211vap *, enum ieee80211_state, int); - struct ieee80211_amrr amrr; }; #define ZYD_VAP(vap) ((struct zyd_vap *)(vap)) diff --git a/sys/dev/wpi/if_wpi.c b/sys/dev/wpi/if_wpi.c index 0517e6b..4ce1fb3 100644 --- a/sys/dev/wpi/if_wpi.c +++ b/sys/dev/wpi/if_wpi.c @@ -93,6 +93,7 @@ __FBSDID("$FreeBSD$"); #include <net80211/ieee80211_var.h> #include <net80211/ieee80211_radiotap.h> #include <net80211/ieee80211_regdomain.h> +#include <net80211/ieee80211_ratectl.h> #include <netinet/in.h> #include <netinet/in_systm.h> @@ -173,8 +174,7 @@ static int wpi_alloc_tx_ring(struct wpi_softc *, struct wpi_tx_ring *, int, int); static void wpi_reset_tx_ring(struct wpi_softc *, struct wpi_tx_ring *); static void wpi_free_tx_ring(struct wpi_softc *, struct wpi_tx_ring *); -static struct ieee80211_node *wpi_node_alloc(struct ieee80211vap *, - const uint8_t mac[IEEE80211_ADDR_LEN]); +static void wpi_newassoc(struct ieee80211_node *, int); static int wpi_newstate(struct ieee80211vap *, enum ieee80211_state, int); static void wpi_mem_lock(struct wpi_softc *); static void wpi_mem_unlock(struct wpi_softc *); @@ -235,7 +235,6 @@ static void wpi_init_locked(struct wpi_softc *, int); static void wpi_stop(struct wpi_softc *); static void wpi_stop_locked(struct wpi_softc *); -static void wpi_newassoc(struct ieee80211_node *, int); static int wpi_set_txpower(struct wpi_softc *, struct ieee80211_channel *, int); static void wpi_calib_timeout(void *); @@ -668,9 +667,8 @@ wpi_attach(device_t dev) ieee80211_ifattach(ic, macaddr); /* override default methods */ - ic->ic_node_alloc = wpi_node_alloc; - ic->ic_newassoc = wpi_newassoc; ic->ic_raw_xmit = wpi_raw_xmit; + ic->ic_newassoc = wpi_newassoc; ic->ic_wme.wme_update = wpi_wme_update; ic->ic_scan_start = wpi_scan_start; ic->ic_scan_end = wpi_scan_end; @@ -782,11 +780,7 @@ wpi_vap_create(struct ieee80211com *ic, wvp->newstate = vap->iv_newstate; vap->iv_newstate = wpi_newstate; - ieee80211_amrr_init(&wvp->amrr, vap, - IEEE80211_AMRR_MIN_SUCCESS_THRESHOLD, - IEEE80211_AMRR_MAX_SUCCESS_THRESHOLD, - 500 /*ms*/); - + ieee80211_ratectl_init(vap); /* complete setup */ ieee80211_vap_attach(vap, ieee80211_media_change, ieee80211_media_status); ic->ic_opmode = opmode; @@ -798,7 +792,7 @@ wpi_vap_delete(struct ieee80211vap *vap) { struct wpi_vap *wvp = WPI_VAP(vap); - ieee80211_amrr_cleanup(&wvp->amrr); + ieee80211_ratectl_deinit(vap); ieee80211_vap_detach(vap); free(wvp, M_80211_VAP); } @@ -1236,18 +1230,6 @@ wpi_resume(device_t dev) return 0; } -/* ARGSUSED */ -static struct ieee80211_node * -wpi_node_alloc(struct ieee80211vap *vap __unused, - const uint8_t mac[IEEE80211_ADDR_LEN] __unused) -{ - struct wpi_node *wn; - - wn = malloc(sizeof (struct wpi_node), M_80211_NODE, M_NOWAIT | M_ZERO); - - return &wn->ni; -} - /** * Called by net80211 when ever there is a change to 80211 state machine */ @@ -1567,7 +1549,9 @@ wpi_tx_intr(struct wpi_softc *sc, struct wpi_rx_desc *desc) struct wpi_tx_ring *ring = &sc->txq[desc->qid & 0x3]; struct wpi_tx_data *txdata = &ring->data[desc->idx]; struct wpi_tx_stat *stat = (struct wpi_tx_stat *)(desc + 1); - struct wpi_node *wn = (struct wpi_node *)txdata->ni; + struct ieee80211_node *ni = txdata->ni; + struct ieee80211vap *vap = ni->ni_vap; + int retrycnt = 0; DPRINTFN(WPI_DEBUG_TX, ("tx done: qid=%d idx=%d retries=%d nkill=%d " "rate=%x duration=%d status=%x\n", desc->qid, desc->idx, @@ -1580,11 +1564,12 @@ wpi_tx_intr(struct wpi_softc *sc, struct wpi_rx_desc *desc) * the lowest available bit-rate. * XXX frames w/o ACK shouldn't be used either */ - wn->amn.amn_txcnt++; if (stat->ntries > 0) { DPRINTFN(WPI_DEBUG_TX, ("%d retries\n", stat->ntries)); - wn->amn.amn_retrycnt++; + retrycnt = 1; } + ieee80211_ratectl_tx_complete(vap, ni, IEEE80211_RATECTL_TX_SUCCESS, + &retrycnt, NULL); /* XXX oerrors should only count errors !maxtries */ if ((le32toh(stat->status) & 0xff) != 1) @@ -1919,7 +1904,7 @@ wpi_tx_data(struct wpi_softc *sc, struct mbuf *m0, struct ieee80211_node *ni, } else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE) { rate = tp->ucastrate; } else { - (void) ieee80211_amrr_choose(ni, &WPI_NODE(ni)->amn); + (void) ieee80211_ratectl_rate(ni, NULL, 0); rate = ni->ni_txrate; } tx->rate = wpi_plcp_signal(rate); @@ -3214,10 +3199,9 @@ wpi_stop(struct wpi_softc *sc) static void wpi_newassoc(struct ieee80211_node *ni, int isnew) { - struct ieee80211vap *vap = ni->ni_vap; - struct wpi_vap *wvp = WPI_VAP(vap); - ieee80211_amrr_node_init(&wvp->amrr, &WPI_NODE(ni)->amn, ni); + /* XXX move */ + ieee80211_ratectl_node_init(ni); } static void @@ -3706,4 +3690,3 @@ static const char *wpi_cmd_str(int cmd) MODULE_DEPEND(wpi, pci, 1, 1, 1); MODULE_DEPEND(wpi, wlan, 1, 1, 1); MODULE_DEPEND(wpi, firmware, 1, 1, 1); -MODULE_DEPEND(wpi, wlan_amrr, 1, 1, 1); diff --git a/sys/dev/wpi/if_wpivar.h b/sys/dev/wpi/if_wpivar.h index 811624b..00579b3e 100644 --- a/sys/dev/wpi/if_wpivar.h +++ b/sys/dev/wpi/if_wpivar.h @@ -106,12 +106,6 @@ struct wpi_amrr { int recovery; }; -struct wpi_node { - struct ieee80211_node ni; /* must be the first */ - struct ieee80211_amrr_node amn; -}; -#define WPI_NODE(ni) ((struct wpi_node *)(ni)) - struct wpi_power_sample { uint8_t index; int8_t power; @@ -127,7 +121,6 @@ struct wpi_power_group { struct wpi_vap { struct ieee80211vap vap; - struct ieee80211_amrr amrr; int (*newstate)(struct ieee80211vap *, enum ieee80211_state, int); diff --git a/sys/modules/wlan/Makefile b/sys/modules/wlan/Makefile index 07233c6..79d5e75 100644 --- a/sys/modules/wlan/Makefile +++ b/sys/modules/wlan/Makefile @@ -3,12 +3,13 @@ .PATH: ${.CURDIR}/../../net80211 KMOD= wlan -SRCS= ieee80211.c ieee80211_action.c ieee80211_ageq.c \ +SRCS= ieee80211.c ieee80211_action.c ieee80211_ageq.c ieee80211_amrr.c \ ieee80211_crypto.c ieee80211_crypto_none.c ieee80211_dfs.c \ ieee80211_freebsd.c ieee80211_input.c ieee80211_ioctl.c \ ieee80211_mesh.c ieee80211_node.c ieee80211_output.c ieee80211_phy.c \ ieee80211_power.c ieee80211_proto.c ieee80211_scan.c \ - ieee80211_scan_sta.c ieee80211_radiotap.c ieee80211_regdomain.c \ + ieee80211_scan_sta.c ieee80211_radiotap.c ieee80211_ratectl.c \ + ieee80211_regdomain.c ieee80211_rssadapt.c \ ieee80211_ht.c ieee80211_hwmp.c ieee80211_adhoc.c ieee80211_hostap.c \ ieee80211_monitor.c ieee80211_sta.c ieee80211_wds.c ieee80211_ddb.c SRCS+= bus_if.h device_if.h opt_inet.h opt_inet6.h opt_ipx.h opt_wlan.h \ diff --git a/sys/net80211/ieee80211.c b/sys/net80211/ieee80211.c index b14f13f..63b500d 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> @@ -483,6 +484,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..6111058 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,49 @@ 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); + amrr = vap->iv_rs = malloc(sizeof(struct ieee80211_amrr), + M_80211_RATECTL, M_NOWAIT|M_ZERO); + if (amrr == NULL) { + if_printf(vap->iv_ifp, "couldn't alloc ratectl structure\n"); + return; + } + 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 = amn = malloc(sizeof(struct ieee80211_amrr_node), + M_80211_RATECTL, M_NOWAIT|M_ZERO); + if (amn == NULL) { + if_printf(vap->iv_ifp, "couldn't alloc per-node ratectl " + "structure\n"); + return; + } amn->amn_amrr = amrr; amn->amn_success = 0; amn->amn_recovery = 0; @@ -112,6 +164,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 +226,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 +247,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 +315,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 23c1fcd..abfc2c0 100644 --- a/sys/net80211/ieee80211_freebsd.h +++ b/sys/net80211/ieee80211_freebsd.h @@ -396,14 +396,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..73b4f32 --- /dev/null +++ b/sys/net80211/ieee80211_ratectl.h @@ -0,0 +1,129 @@ +/*- + * 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 1 +#define IEEE80211_RATECTL_TX_FAILURE 0 + +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; + + if (ni->ni_rctls == NULL) /* ratectl not setup */ + return; + 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 0; + 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..ad329e0 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,29 @@ 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__)); + + vap->iv_rs = rs = malloc(sizeof(struct ieee80211_rssadapt), + M_80211_RATECTL, M_NOWAIT|M_ZERO); + if (rs == NULL) { + if_printf(vap->iv_ifp, "couldn't alloc ratectl structure\n"); + return; + } 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 +161,21 @@ 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 ieee80211vap *vap = ni->ni_vap; + struct ieee80211_rssadapt *rsa = vap->iv_rs; const struct ieee80211_rateset *rs = &ni->ni_rates; + ni->ni_rctls = ra = malloc(sizeof(struct ieee80211_rssadapt_node), + M_80211_RATECTL, M_NOWAIT|M_ZERO); + if (ra == NULL) { + if_printf(vap->iv_ifp, "couldn't alloc per-node ratectl " + "structure\n"); + return; + } ra->ra_rs = rsa; ra->ra_rates = *rs; rssadapt_updatestats(ra); @@ -140,6 +192,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 +214,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 +253,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 +273,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 +301,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 1a58cac..26c5c4dd 100644 --- a/sys/net80211/ieee80211_var.h +++ b/sys/net80211/ieee80211_var.h @@ -433,6 +433,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 */ @@ -468,7 +471,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); |