diff options
author | Damien Bergamini <damien@cvs.openbsd.org> | 2006-06-14 19:31:48 +0000 |
---|---|---|
committer | Damien Bergamini <damien@cvs.openbsd.org> | 2006-06-14 19:31:48 +0000 |
commit | 847bf49bad264b13a0af4189e5a09ab523bd15fb (patch) | |
tree | c4fe4b3799898a823db91920ef09966505b41c6b | |
parent | 703a01ef40649180abe647d36fb34abffe0ed912 (diff) |
must use RTS/CTS protection when sending frames at OFDM rates in a BSS
with non-ERP STAs. some bits are missing in net80211 though, so this
code won't be triggered yet.
-rw-r--r-- | sys/dev/ic/rt2560.c | 38 | ||||
-rw-r--r-- | sys/dev/ic/rt2661.c | 57 | ||||
-rw-r--r-- | sys/dev/ic/rt2661reg.h | 4 | ||||
-rw-r--r-- | sys/dev/pci/if_wpi.c | 8 |
4 files changed, 63 insertions, 44 deletions
diff --git a/sys/dev/ic/rt2560.c b/sys/dev/ic/rt2560.c index 10dc258e53e..e1577516ae2 100644 --- a/sys/dev/ic/rt2560.c +++ b/sys/dev/ic/rt2560.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rt2560.c,v 1.18 2006/06/10 20:30:00 damien Exp $ */ +/* $OpenBSD: rt2560.c,v 1.19 2006/06/14 19:31:47 damien Exp $ */ /*- * Copyright (c) 2005, 2006 @@ -1673,7 +1673,7 @@ rt2560_tx_mgt(struct rt2560_softc *sc, struct mbuf *m0, RAL_SIFS; *(uint16_t *)wh->i_dur = htole16(dur); - /* tell hardware to add timestamp for probe responses */ + /* tell hardware to set timestamp for probe responses */ if ((wh->i_fc[0] & (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_MASK)) == (IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_PROBE_RESP)) @@ -1746,7 +1746,7 @@ rt2560_tx_data(struct rt2560_softc *sc, struct mbuf *m0, struct mbuf *mnew; uint16_t dur; uint32_t flags = 0; - int rate, error; + int rate, useprot, error; wh = mtod(m0, struct ieee80211_frame *); @@ -1778,13 +1778,19 @@ rt2560_tx_data(struct rt2560_softc *sc, struct mbuf *m0, wh = mtod(m0, struct ieee80211_frame *); } - /* + /*- * IEEE Std 802.11-1999, pp 82: "A STA shall use an RTS/CTS exchange * for directed frames only when the length of the MPDU is greater - * than the length threshold indicated by [...]" ic_rtsthreshold. + * than the length threshold indicated by" ic_rtsthreshold. + * + * IEEE Std 802.11-2003g, pp 13: "ERP STAs shall use protection + * mechanism (such as RTS/CTS or CTS-to-self) for ERP-OFDM MPDUs of + * type Data or an MMPDU". */ - if (!IEEE80211_IS_MULTICAST(wh->i_addr1) && - m0->m_pkthdr.len > ic->ic_rtsthreshold) { + useprot = !IEEE80211_IS_MULTICAST(wh->i_addr1) && + (m0->m_pkthdr.len + IEEE80211_CRC_LEN > ic->ic_rtsthreshold || + ((ic->ic_flags & IEEE80211_F_USEPROT) && RAL_RATE_IS_OFDM(rate))); + if (useprot) { struct mbuf *m; uint16_t dur; int rtsrate, ackrate; @@ -1798,6 +1804,12 @@ rt2560_tx_data(struct rt2560_softc *sc, struct mbuf *m0, 3 * RAL_SIFS; m = rt2560_get_rts(sc, wh, dur); + if (m == NULL) { + printf("%s: could not allocate RTS frame\n", + sc->sc_dev.dv_xname); + m_freem(m0); + return ENOBUFS; + } desc = &sc->txq.desc[sc->txq.cur_encrypt]; data = &sc->txq.data[sc->txq.cur_encrypt]; @@ -1836,9 +1848,9 @@ rt2560_tx_data(struct rt2560_softc *sc, struct mbuf *m0, (sc->txq.cur_encrypt + 1) % RT2560_TX_RING_COUNT; /* - * IEEE Std 802.11-1999: when an RTS/CTS exchange is used, the + * IEEE Std 802.11-1999: "when an RTS/CTS exchange is used, the * asynchronous data frame shall be transmitted after the CTS - * frame and a SIFS period. + * frame and a SIFS period". */ flags |= RT2560_TX_LONG_RETRY | RT2560_TX_IFS_SIFS; } @@ -1979,8 +1991,7 @@ rt2560_start(struct ifnet *ifp) m0->m_pkthdr.rcvif = NULL; #if NBPFILTER > 0 if (ic->ic_rawbpf != NULL) - bpf_mtap(ic->ic_rawbpf, m0, - BPF_DIRECTION_OUT); + bpf_mtap(ic->ic_rawbpf, m0, BPF_DIRECTION_OUT); #endif if (rt2560_tx_mgt(sc, m0, ni) != 0) break; @@ -2005,8 +2016,7 @@ rt2560_start(struct ifnet *ifp) continue; #if NBPFILTER > 0 if (ic->ic_rawbpf != NULL) - bpf_mtap(ic->ic_rawbpf, m0, - BPF_DIRECTION_OUT); + bpf_mtap(ic->ic_rawbpf, m0, BPF_DIRECTION_OUT); #endif if (rt2560_tx_data(sc, m0, ni) != 0) { if (ni != NULL) @@ -2799,5 +2809,5 @@ rt2560_shutdown(void *arg) } struct cfdriver ral_cd = { - 0, "ral", DV_IFNET + NULL, "ral", DV_IFNET }; diff --git a/sys/dev/ic/rt2661.c b/sys/dev/ic/rt2661.c index fcbf4e06c2c..f9cce6bfd30 100644 --- a/sys/dev/ic/rt2661.c +++ b/sys/dev/ic/rt2661.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rt2661.c,v 1.20 2006/06/10 20:31:59 damien Exp $ */ +/* $OpenBSD: rt2661.c,v 1.21 2006/06/14 19:31:47 damien Exp $ */ /*- * Copyright (c) 2006 @@ -183,9 +183,6 @@ static const struct { RT2661_DEF_BBP }; -/* - * Default settings for RF registers; values taken from the reference driver. - */ static const struct rfprog { uint8_t chan; uint32_t r1, r2, r3, r4; @@ -1118,9 +1115,8 @@ rt2661_rx_intr(struct rt2661_softc *sc) htole64(((uint64_t)tsf_hi << 32) | tsf_lo); tap->wr_flags = 0; tap->wr_rate = rt2661_rxrate(desc); - tap->wr_chan_freq = htole16(ic->ic_ibss_chan->ic_freq); - tap->wr_chan_flags = - htole16(ic->ic_ibss_chan->ic_flags); + tap->wr_chan_freq = htole16(sc->sc_curchan->ic_freq); + tap->wr_chan_flags = htole16(sc->sc_curchan->ic_flags); tap->wr_antsignal = desc->rssi; M_DUP_PKTHDR(&mb, m); @@ -1172,7 +1168,6 @@ skip: desc->flags |= htole32(RT2661_RX_BUSY); rt2661_start(ifp); } -/* ARGSUSED */ void rt2661_mcu_beacon_expire(struct rt2661_softc *sc) { @@ -1490,8 +1485,8 @@ rt2661_tx_mgt(struct rt2661_softc *sc, struct mbuf *m0, tap->wt_flags = 0; tap->wt_rate = rate; - tap->wt_chan_freq = htole16(ic->ic_ibss_chan->ic_freq); - tap->wt_chan_flags = htole16(ic->ic_ibss_chan->ic_flags); + tap->wt_chan_freq = htole16(sc->sc_curchan->ic_freq); + tap->wt_chan_flags = htole16(sc->sc_curchan->ic_flags); M_DUP_PKTHDR(&mb, m0); mb.m_data = (caddr_t)tap; @@ -1512,7 +1507,7 @@ rt2661_tx_mgt(struct rt2661_softc *sc, struct mbuf *m0, RAL_SIFS; *(uint16_t *)wh->i_dur = htole16(dur); - /* tell hardware to add timestamp in probe responses */ + /* tell hardware to set timestamp in probe responses */ if ((wh->i_fc[0] & (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_MASK)) == (IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_PROBE_RESP)) @@ -1587,7 +1582,7 @@ rt2661_tx_data(struct rt2661_softc *sc, struct mbuf *m0, struct mbuf *mnew; uint16_t dur; uint32_t flags = 0; - int rate, error; + int rate, useprot, error; wh = mtod(m0, struct ieee80211_frame *); @@ -1619,13 +1614,19 @@ rt2661_tx_data(struct rt2661_softc *sc, struct mbuf *m0, wh = mtod(m0, struct ieee80211_frame *); } - /* + /*- * IEEE Std 802.11-1999, pp 82: "A STA shall use an RTS/CTS exchange * for directed frames only when the length of the MPDU is greater - * than the length threshold indicated by [...]" ic_rtsthreshold. + * than the length threshold indicated by" ic_rtsthreshold. + * + * IEEE Std 802.11-2003g, pp 13: "ERP STAs shall use protection + * mechanism (such as RTS/CTS or CTS-to-self) for ERP-OFDM MPDUs of + * type Data or an MMPDU". */ - if (!IEEE80211_IS_MULTICAST(wh->i_addr1) && - m0->m_pkthdr.len + IEEE80211_CRC_LEN > ic->ic_rtsthreshold) { + useprot = !IEEE80211_IS_MULTICAST(wh->i_addr1) && + (m0->m_pkthdr.len + IEEE80211_CRC_LEN > ic->ic_rtsthreshold || + ((ic->ic_flags & IEEE80211_F_USEPROT) && RAL_RATE_IS_OFDM(rate))); + if (useprot) { struct mbuf *m; uint16_t dur; int rtsrate, ackrate; @@ -1639,6 +1640,12 @@ rt2661_tx_data(struct rt2661_softc *sc, struct mbuf *m0, 3 * RAL_SIFS; m = rt2661_get_rts(sc, wh, dur); + if (m == NULL) { + printf("%s: could not allocate RTS frame\n", + sc->sc_dev.dv_xname); + m_freem(m0); + return ENOBUFS; + } desc = &txq->desc[txq->cur]; data = &txq->data[txq->cur]; @@ -1676,11 +1683,11 @@ rt2661_tx_data(struct rt2661_softc *sc, struct mbuf *m0, txq->cur = (txq->cur + 1) % RT2661_TX_RING_COUNT; /* - * IEEE Std 802.11-1999: when an RTS/CTS exchange is used, the + * IEEE Std 802.11-1999: "when an RTS/CTS exchange is used, the * asynchronous data frame shall be transmitted after the CTS - * frame and a SIFS period. + * frame and a SIFS period". */ - flags |= RT2661_TX_LONG_RETRY | RT2661_TX_IFS; + flags |= RT2661_TX_LONG_RETRY | RT2661_TX_IFS_SIFS; } data = &txq->data[txq->cur]; @@ -1738,8 +1745,8 @@ rt2661_tx_data(struct rt2661_softc *sc, struct mbuf *m0, tap->wt_flags = 0; tap->wt_rate = rate; - tap->wt_chan_freq = htole16(ic->ic_ibss_chan->ic_freq); - tap->wt_chan_flags = htole16(ic->ic_ibss_chan->ic_flags); + tap->wt_chan_freq = htole16(sc->sc_curchan->ic_freq); + tap->wt_chan_flags = htole16(sc->sc_curchan->ic_flags); M_DUP_PKTHDR(&mb, m0); mb.m_data = (caddr_t)tap; @@ -1817,8 +1824,7 @@ rt2661_start(struct ifnet *ifp) m0->m_pkthdr.rcvif = NULL; #if NBPFILTER > 0 if (ic->ic_rawbpf != NULL) - bpf_mtap(ic->ic_rawbpf, m0, - BPF_DIRECTION_OUT); + bpf_mtap(ic->ic_rawbpf, m0, BPF_DIRECTION_OUT); #endif if (rt2661_tx_mgt(sc, m0, ni) != 0) break; @@ -2912,7 +2918,7 @@ rt2661_power(int why, void *arg) int s; DPRINTF(("%s: rt2661_power(%d)\n", sc->sc_dev.dv_xname, why)); - + s = splnet(); switch (why) { case PWR_SUSPEND: @@ -2940,7 +2946,6 @@ rt2661_shutdown(void *arg) { struct rt2661_softc *sc = arg; struct ifnet *ifp = &sc->sc_ic.ic_if; - + rt2661_stop(ifp, 1); } - diff --git a/sys/dev/ic/rt2661reg.h b/sys/dev/ic/rt2661reg.h index 4f137c045f0..d99d15c005f 100644 --- a/sys/dev/ic/rt2661reg.h +++ b/sys/dev/ic/rt2661reg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: rt2661reg.h,v 1.6 2006/06/10 20:31:59 damien Exp $ */ +/* $OpenBSD: rt2661reg.h,v 1.7 2006/06/14 19:31:47 damien Exp $ */ /*- * Copyright (c) 2006 @@ -218,7 +218,7 @@ struct rt2661_tx_desc { #define RT2661_TX_NEED_ACK (1 << 3) #define RT2661_TX_TIMESTAMP (1 << 4) #define RT2661_TX_OFDM (1 << 5) -#define RT2661_TX_IFS (1 << 6) +#define RT2661_TX_IFS_SIFS (1 << 6) #define RT2661_TX_LONG_RETRY (1 << 7) #define RT2661_TX_BURST (1 << 28) diff --git a/sys/dev/pci/if_wpi.c b/sys/dev/pci/if_wpi.c index 7635a8312f3..2004d8a51bb 100644 --- a/sys/dev/pci/if_wpi.c +++ b/sys/dev/pci/if_wpi.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_wpi.c,v 1.17 2006/06/14 18:40:23 brad Exp $ */ +/* $OpenBSD: if_wpi.c,v 1.18 2006/06/14 19:31:47 damien Exp $ */ /*- * Copyright (c) 2006 @@ -1422,6 +1422,9 @@ wpi_plcp_signal(int rate) } } +/* quickly determine if a given rate is CCK or OFDM */ +#define WPI_RATE_IS_OFDM(rate) ((rate) >= 12 && (rate) != 22) + int wpi_tx_data(struct wpi_softc *sc, struct mbuf *m0, struct ieee80211_node *ni, int ac) @@ -1498,7 +1501,8 @@ wpi_tx_data(struct wpi_softc *sc, struct mbuf *m0, struct ieee80211_node *ni, if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) tx->flags |= htole32(WPI_TX_NEED_ACK); - else if (m0->m_pkthdr.len + IEEE80211_CRC_LEN > ic->ic_rtsthreshold) + else if (m0->m_pkthdr.len + IEEE80211_CRC_LEN > ic->ic_rtsthreshold || + ((ic->ic_flags & IEEE80211_F_USEPROT) && WPI_RATE_IS_OFDM(rate))) tx->flags |= htole32(WPI_TX_NEED_RTS | WPI_TX_FULL_TXOP); tx->flags |= htole32(WPI_TX_AUTO_SEQ); |