- Implement ieee80211_ack_rate() according to IEEE Std 802.11g-2003
authorSepherosa Ziehau <sephe@dragonflybsd.org>
Tue, 27 Mar 2007 13:34:53 +0000 (13:34 +0000)
committerSepherosa Ziehau <sephe@dragonflybsd.org>
Tue, 27 Mar 2007 13:34:53 +0000 (13:34 +0000)
  clause 9.6
- Nuke non-standard conforming ACK rate calculation in ral(4), rum(4)
  and ural(4).  Use ieee80211_ack_rate() instead.

sys/dev/netif/ral/rt2560.c
sys/dev/netif/ral/rt2661.c
sys/dev/netif/rum/if_rum.c
sys/dev/netif/ural/if_ural.c
sys/netproto/802_11/ieee80211_proto.h
sys/netproto/802_11/wlan/ieee80211_output.c

index 062edba..be837a1 100644 (file)
@@ -15,7 +15,7 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  *
  * $FreeBSD: src/sys/dev/ral/rt2560.c,v 1.3 2006/03/21 21:15:43 damien Exp $
- * $DragonFly: src/sys/dev/netif/ral/rt2560.c,v 1.10 2007/02/06 12:38:30 sephe Exp $
+ * $DragonFly: src/sys/dev/netif/ral/rt2560.c,v 1.11 2007/03/27 13:34:53 sephe Exp $
  */
 
 /*
@@ -97,7 +97,6 @@ static void           rt2560_rx_intr(struct rt2560_softc *);
 static void            rt2560_beacon_expire(struct rt2560_softc *);
 static void            rt2560_wakeup_expire(struct rt2560_softc *);
 static uint8_t         rt2560_rxrate(struct rt2560_rx_desc *);
-static int             rt2560_ack_rate(struct ieee80211com *, int);
 static uint16_t                rt2560_txtime(int, int, uint32_t);
 static uint8_t         rt2560_plcp_signal(int);
 static void            rt2560_setup_tx_desc(struct rt2560_softc *,
@@ -1502,40 +1501,6 @@ rt2560_rxrate(struct rt2560_rx_desc *desc)
        return 2;       /* should not get there */
 }
 
-/*
- * Return the expected ack rate for a frame transmitted at rate `rate'.
- * XXX: this should depend on the destination node basic rate set.
- */
-static int
-rt2560_ack_rate(struct ieee80211com *ic, int rate)
-{
-       switch (rate) {
-       /* CCK rates */
-       case 2:
-               return 2;
-       case 4:
-       case 11:
-       case 22:
-               return (ic->ic_curmode == IEEE80211_MODE_11B) ? 4 : rate;
-
-       /* OFDM rates */
-       case 12:
-       case 18:
-               return 12;
-       case 24:
-       case 36:
-               return 24;
-       case 48:
-       case 72:
-       case 96:
-       case 108:
-               return 48;
-       }
-
-       /* default to 1Mbps */
-       return 2;
-}
-
 /*
  * Compute the duration (in us) needed to transmit `len' bytes at rate `rate'.
  * The function automatically determines the operating mode depending on the
@@ -1851,7 +1816,7 @@ rt2560_tx_data(struct rt2560_softc *sc, struct mbuf *m0,
                int rtsrate, ackrate;
 
                rtsrate = IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan) ? 12 : 2;
-               ackrate = rt2560_ack_rate(ic, rate);
+               ackrate = ieee80211_ack_rate(ni, rate);
 
                dur = rt2560_txtime(m0->m_pkthdr.len + 4, rate, ic->ic_flags) +
                      rt2560_txtime(RAL_CTS_SIZE, rtsrate, ic->ic_flags) +
@@ -1961,8 +1926,7 @@ rt2560_tx_data(struct rt2560_softc *sc, struct mbuf *m0,
 
        if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
                flags |= RT2560_TX_ACK;
-
-               dur = rt2560_txtime(RAL_ACK_SIZE, rt2560_ack_rate(ic, rate),
+               dur = rt2560_txtime(RAL_ACK_SIZE, ieee80211_ack_rate(ni, rate),
                    ic->ic_flags) + RAL_SIFS;
                *(uint16_t *)wh->i_dur = htole16(dur);
        }
index 78d9e38..217a6d1 100644 (file)
@@ -15,7 +15,7 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  *
  * $FreeBSD: src/sys/dev/ral/rt2661.c,v 1.4 2006/03/21 21:15:43 damien Exp $
- * $DragonFly: src/sys/dev/netif/ral/rt2661.c,v 1.13 2007/02/07 12:34:26 sephe Exp $
+ * $DragonFly: src/sys/dev/netif/ral/rt2661.c,v 1.14 2007/03/27 13:34:53 sephe Exp $
  */
 
 /*
@@ -95,7 +95,6 @@ static void           rt2661_tx_dma_intr(struct rt2661_softc *,
 static void            rt2661_mcu_beacon_expire(struct rt2661_softc *);
 static void            rt2661_mcu_wakeup(struct rt2661_softc *);
 static void            rt2661_mcu_cmd_intr(struct rt2661_softc *);
-static int             rt2661_ack_rate(struct ieee80211com *, int);
 static uint16_t                rt2661_txtime(int, int, uint32_t);
 static uint8_t         rt2661_rxrate(struct rt2661_rx_desc *);
 static uint8_t         rt2661_plcp_signal(int);
@@ -1393,40 +1392,6 @@ rt2661_rxrate(struct rt2661_rx_desc *desc)
        return 2;       /* should not get there */
 }
 
-/*
- * Return the expected ack rate for a frame transmitted at rate `rate'.
- * XXX: this should depend on the destination node basic rate set.
- */
-static int
-rt2661_ack_rate(struct ieee80211com *ic, int rate)
-{
-       switch (rate) {
-       /* CCK rates */
-       case 2:
-               return 2;
-       case 4:
-       case 11:
-       case 22:
-               return (ic->ic_curmode == IEEE80211_MODE_11B) ? 4 : rate;
-
-       /* OFDM rates */
-       case 12:
-       case 18:
-               return 12;
-       case 24:
-       case 36:
-               return 24;
-       case 48:
-       case 72:
-       case 96:
-       case 108:
-               return 48;
-       }
-
-       /* default to 1Mbps */
-       return 2;
-}
-
 /*
  * Compute the duration (in us) needed to transmit `len' bytes at rate `rate'.
  * The function automatically determines the operating mode depending on the
@@ -1711,7 +1676,7 @@ rt2661_tx_data(struct rt2661_softc *sc, struct mbuf *m0,
                int rtsrate, ackrate;
 
                rtsrate = IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan) ? 12 : 2;
-               ackrate = rt2661_ack_rate(ic, rate);
+               ackrate = ieee80211_ack_rate(ni, rate);
 
                dur = rt2661_txtime(m0->m_pkthdr.len + 4, rate, ic->ic_flags) +
                      rt2661_txtime(RAL_CTS_SIZE, rtsrate, ic->ic_flags) +
@@ -1820,7 +1785,7 @@ rt2661_tx_data(struct rt2661_softc *sc, struct mbuf *m0,
        if (!noack && !IEEE80211_IS_MULTICAST(wh->i_addr1)) {
                flags |= RT2661_TX_NEED_ACK;
 
-               dur = rt2661_txtime(RAL_ACK_SIZE, rt2661_ack_rate(ic, rate),
+               dur = rt2661_txtime(RAL_ACK_SIZE, ieee80211_ack_rate(ni, rate),
                    ic->ic_flags) + RAL_SIFS;
                *(uint16_t *)wh->i_dur = htole16(dur);
        }
index a4ecfcb..ca00f3f 100644 (file)
@@ -1,5 +1,5 @@
 /*     $OpenBSD: if_rum.c,v 1.40 2006/09/18 16:20:20 damien Exp $      */
-/*     $DragonFly: src/sys/dev/netif/rum/if_rum.c,v 1.8 2007/03/18 11:49:32 sephe Exp $        */
+/*     $DragonFly: src/sys/dev/netif/rum/if_rum.c,v 1.9 2007/03/27 13:34:53 sephe Exp $        */
 
 /*-
  * Copyright (c) 2005, 2006 Damien Bergamini <damien.bergamini@free.fr>
@@ -131,7 +131,6 @@ Static void         rum_txeof(usbd_xfer_handle, usbd_private_handle,
 Static void            rum_rxeof(usbd_xfer_handle, usbd_private_handle,
                            usbd_status);
 Static uint8_t         rum_rxrate(struct rum_rx_desc *);
-Static int             rum_ack_rate(struct ieee80211com *, int);
 Static uint16_t                rum_txtime(int, int, uint32_t);
 Static uint8_t         rum_plcp_signal(int);
 Static void            rum_setup_tx_desc(struct rum_softc *,
@@ -941,40 +940,6 @@ rum_rxrate(struct rum_rx_desc *desc)
        return 2;       /* should not get there */
 }
 
-/*
- * Return the expected ack rate for a frame transmitted at rate `rate'.
- * XXX: this should depend on the destination node basic rate set.
- */
-Static int
-rum_ack_rate(struct ieee80211com *ic, int rate)
-{
-       switch (rate) {
-       /* CCK rates */
-       case 2:
-               return 2;
-       case 4:
-       case 11:
-       case 22:
-               return (ic->ic_curmode == IEEE80211_MODE_11B) ? 4 : rate;
-
-       /* OFDM rates */
-       case 12:
-       case 18:
-               return 12;
-       case 24:
-       case 36:
-               return 24;
-       case 48:
-       case 72:
-       case 96:
-       case 108:
-               return 48;
-       }
-
-       /* default to 1Mbps */
-       return 2;
-}
-
 /*
  * Compute the duration (in us) needed to transmit `len' bytes at rate `rate'.
  * The function automatically determines the operating mode depending on the
@@ -1122,7 +1087,7 @@ rum_tx_data(struct rum_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
        if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
                flags |= RT2573_TX_ACK;
 
-               dur = rum_txtime(RUM_ACK_SIZE, rum_ack_rate(ic, rate),
+               dur = rum_txtime(RUM_ACK_SIZE, ieee80211_ack_rate(ni, rate),
                    ic->ic_flags) + sc->sifs;
                *(uint16_t *)wh->i_dur = htole16(dur);
 
index 31f483b..bb60af3 100644 (file)
@@ -1,5 +1,5 @@
 /*     $FreeBSD: src/sys/dev/usb/if_ural.c,v 1.10.2.8 2006/07/08 07:48:43 maxim Exp $  */
-/*     $DragonFly: src/sys/dev/netif/ural/if_ural.c,v 1.7 2007/03/18 11:49:32 sephe Exp $      */
+/*     $DragonFly: src/sys/dev/netif/ural/if_ural.c,v 1.8 2007/03/27 13:34:53 sephe Exp $      */
 
 /*-
  * Copyright (c) 2005, 2006
@@ -115,7 +115,6 @@ Static void         ural_txeof(usbd_xfer_handle, usbd_private_handle,
                            usbd_status);
 Static void            ural_rxeof(usbd_xfer_handle, usbd_private_handle,
                            usbd_status);
-Static int             ural_ack_rate(struct ieee80211com *, int);
 Static uint16_t                ural_txtime(int, int, uint32_t);
 Static uint8_t         ural_plcp_signal(int);
 Static void            ural_setup_tx_desc(struct ural_softc *,
@@ -1032,40 +1031,6 @@ skip:    /* setup a new transfer */
        usbd_transfer(xfer);
 }
 
-/*
- * Return the expected ack rate for a frame transmitted at rate `rate'.
- * XXX: this should depend on the destination node basic rate set.
- */
-Static int
-ural_ack_rate(struct ieee80211com *ic, int rate)
-{
-       switch (rate) {
-       /* CCK rates */
-       case 2:
-               return 2;
-       case 4:
-       case 11:
-       case 22:
-               return (ic->ic_curmode == IEEE80211_MODE_11B) ? 4 : rate;
-
-       /* OFDM rates */
-       case 12:
-       case 18:
-               return 12;
-       case 24:
-       case 36:
-               return 24;
-       case 48:
-       case 72:
-       case 96:
-       case 108:
-               return 48;
-       }
-
-       /* default to 1Mbps */
-       return 2;
-}
-
 /*
  * Compute the duration (in us) needed to transmit `len' bytes at rate `rate'.
  * The function automatically determines the operating mode depending on the
@@ -1330,7 +1295,7 @@ ural_tx_data(struct ural_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
                flags |= RAL_TX_ACK;
                flags |= RAL_TX_RETRY(sc->sc_tx_retries);
 
-               dur = ural_txtime(RAL_ACK_SIZE, ural_ack_rate(ic, rate),
+               dur = ural_txtime(RAL_ACK_SIZE, ieee80211_ack_rate(ni, rate),
                    ic->ic_flags) + RAL_SIFS;
                *(uint16_t *)wh->i_dur = htole16(dur);
        }
index 9a985b2..6adb623 100644 (file)
@@ -30,7 +30,7 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/net80211/ieee80211_proto.h,v 1.11.2.5 2006/02/12 19:00:39 sam Exp $
- * $DragonFly: src/sys/netproto/802_11/ieee80211_proto.h,v 1.8 2007/01/01 08:51:45 sephe Exp $
+ * $DragonFly: src/sys/netproto/802_11/ieee80211_proto.h,v 1.9 2007/03/27 13:34:53 sephe Exp $
  */
 #ifndef _NET80211_IEEE80211_PROTO_H_
 #define _NET80211_IEEE80211_PROTO_H_
@@ -254,6 +254,8 @@ int ieee80211_beacon_update(struct ieee80211com *,
 struct mbuf *ieee80211_probe_resp_alloc(struct ieee80211com *,
                struct ieee80211_node *);
 
+uint8_t        ieee80211_ack_rate(struct ieee80211_node *, uint8_t);
+
 /*
  * Notification methods called from the 802.11 state machine.
  * Note that while these are defined here, their implementation
index 6ef15f8..a43c62f 100644 (file)
@@ -30,7 +30,7 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/net80211/ieee80211_output.c,v 1.26.2.8 2006/09/02 15:06:04 sam Exp $
- * $DragonFly: src/sys/netproto/802_11/wlan/ieee80211_output.c,v 1.17 2007/03/18 05:35:54 sephe Exp $
+ * $DragonFly: src/sys/netproto/802_11/wlan/ieee80211_output.c,v 1.18 2007/03/27 13:34:53 sephe Exp $
  */
 
 #include "opt_inet.h"
@@ -1801,3 +1801,77 @@ ieee80211_pwrsave(struct ieee80211com *ic, struct ieee80211_node *ni,
        if (qlen == 1)
                ic->ic_set_tim(ni, 1);
 }
+
+#define IEEE80211_MODTYPE_CCK  0
+#define IEEE80211_MODTYPE_OFDM 1
+#define IEEE80211_MODTYPE_PBCC 2
+
+static int
+ieee80211_rate2modtype(uint8_t rate)
+{
+       if (rate == 44)
+               return IEEE80211_MODTYPE_PBCC;
+       else if (rate == 22 || rate < 12)
+               return IEEE80211_MODTYPE_CCK;
+       else
+               return IEEE80211_MODTYPE_OFDM;
+}
+
+uint8_t
+ieee80211_ack_rate(struct ieee80211_node *ni, uint8_t rate)
+{
+       const struct ieee80211_rateset *rs = &ni->ni_rates;
+       uint8_t ack_rate = 0;
+       int modtype, i;
+
+       modtype = ieee80211_rate2modtype(rate);
+
+       for (i = 0; i < rs->rs_nrates; ++i) {
+               uint8_t rate1 = IEEE80211_RS_RATE(rs, i);
+
+               if (rate1 > rate) {
+                       if (ack_rate != 0)
+                               return ack_rate;
+                       else
+                               break;
+               }
+
+               if ((rs->rs_rates[i] & IEEE80211_RATE_BASIC) &&
+                   ieee80211_rate2modtype(rate1) == modtype)
+                       ack_rate = rate1;
+       }
+
+       switch (rate) {
+       /* CCK */
+       case 2:
+       case 4:
+       case 11:
+       case 22:
+               ack_rate = rate;
+               break;
+
+       /* PBCC */
+       case 44:
+               ack_rate = 22;
+               break;
+
+       /* OFDM */
+       case 12:
+       case 18:
+               ack_rate = 12;
+               break;
+       case 24:
+       case 36:
+               ack_rate = 24;
+               break;
+       case 48:
+       case 72:
+       case 96:
+       case 108:
+               ack_rate = 48;
+               break;
+       default:
+               panic("unsupported rate %d\n", rate);
+       }
+       return ack_rate;
+}