net80211: wrap protection frame allocation into ieee80211_alloc_prot()

Move copy-pasted code for RTS/CTS frame allocation into net80211.
While here, add stat / debug message for allocation failures
(copied from run(4)) + return error here in bwn(4).

Reviewed by:	adrian
Differential Revision:	https://reviews.freebsd.org/D14628
This commit is contained in:
Andriy Voskoboinyk 2018-03-09 11:33:56 +00:00
parent e150585e9e
commit d1b671061b
8 changed files with 111 additions and 180 deletions

View File

@ -6401,15 +6401,14 @@ bwn_set_txhdr(struct bwn_mac *mac, struct ieee80211_node *ni,
struct bwn_softc *sc = mac->mac_sc;
struct ieee80211_frame *wh;
struct ieee80211_frame *protwh;
struct ieee80211_frame_cts *cts;
struct ieee80211_frame_rts *rts;
const struct ieee80211_txparam *tp = ni->ni_txparms;
struct ieee80211vap *vap = ni->ni_vap;
struct ieee80211com *ic = &sc->sc_ic;
struct mbuf *mprot;
uint8_t *prot_ptr;
unsigned int len;
uint32_t macctl = 0;
int protdur, rts_rate, rts_rate_fb, ismcast, isshort, rix, type;
int rts_rate, rts_rate_fb, ismcast, isshort, rix, type;
uint16_t phyctl = 0;
uint8_t rate, rate_fb;
int fill_phy_ctl1 = 0;
@ -6528,7 +6527,8 @@ bwn_set_txhdr(struct bwn_mac *mac, struct ieee80211_node *ni,
m->m_pkthdr.len + IEEE80211_CRC_LEN > vap->iv_rtsthreshold)
macctl |= BWN_TX_MAC_LONGFRAME;
if (ic->ic_flags & IEEE80211_F_USEPROT) {
if ((ic->ic_flags & IEEE80211_F_USEPROT) &&
ic->ic_protmode != IEEE80211_PROT_NONE) {
/* Note: don't fall back to CCK rates for 5G */
if (phy->gmode)
rts_rate = BWN_CCK_RATE_1MB;
@ -6537,60 +6537,34 @@ bwn_set_txhdr(struct bwn_mac *mac, struct ieee80211_node *ni,
rts_rate_fb = bwn_get_fbrate(rts_rate);
/* XXX 'rate' here is hardware rate now, not the net80211 rate */
protdur = ieee80211_compute_duration(ic->ic_rt,
m->m_pkthdr.len, rate, isshort) +
+ ieee80211_ack_duration(ic->ic_rt, rate, isshort);
mprot = ieee80211_alloc_prot(ni, m, rate, ic->ic_protmode);
if (mprot == NULL) {
if_inc_counter(vap->iv_ifp, IFCOUNTER_OERRORS, 1);
device_printf(sc->sc_dev,
"could not allocate mbuf for protection mode %d\n",
ic->ic_protmode);
return (ENOBUFS);
}
switch (mac->mac_fw.fw_hdr_format) {
case BWN_FW_HDR_351:
prot_ptr = txhdr->body.r351.rts_frame;
break;
case BWN_FW_HDR_410:
prot_ptr = txhdr->body.r410.rts_frame;
break;
case BWN_FW_HDR_598:
prot_ptr = txhdr->body.r598.rts_frame;
break;
}
bcopy(mtod(mprot, uint8_t *), prot_ptr, mprot->m_pkthdr.len);
m_freem(mprot);
if (ic->ic_protmode == IEEE80211_PROT_CTSONLY) {
switch (mac->mac_fw.fw_hdr_format) {
case BWN_FW_HDR_351:
cts = (struct ieee80211_frame_cts *)
txhdr->body.r351.rts_frame;
break;
case BWN_FW_HDR_410:
cts = (struct ieee80211_frame_cts *)
txhdr->body.r410.rts_frame;
break;
case BWN_FW_HDR_598:
cts = (struct ieee80211_frame_cts *)
txhdr->body.r598.rts_frame;
break;
}
mprot = ieee80211_alloc_cts(ic, ni->ni_vap->iv_myaddr,
protdur);
KASSERT(mprot != NULL, ("failed to alloc mbuf\n"));
bcopy(mtod(mprot, uint8_t *), (uint8_t *)cts,
mprot->m_pkthdr.len);
m_freem(mprot);
macctl |= BWN_TX_MAC_SEND_CTSTOSELF;
len = sizeof(struct ieee80211_frame_cts);
} else {
switch (mac->mac_fw.fw_hdr_format) {
case BWN_FW_HDR_351:
rts = (struct ieee80211_frame_rts *)
txhdr->body.r351.rts_frame;
break;
case BWN_FW_HDR_410:
rts = (struct ieee80211_frame_rts *)
txhdr->body.r410.rts_frame;
break;
case BWN_FW_HDR_598:
rts = (struct ieee80211_frame_rts *)
txhdr->body.r598.rts_frame;
break;
}
/* XXX rate/rate_fb is the hardware rate */
protdur += ieee80211_ack_duration(ic->ic_rt, rate,
isshort);
mprot = ieee80211_alloc_rts(ic, wh->i_addr1,
wh->i_addr2, protdur);
KASSERT(mprot != NULL, ("failed to alloc mbuf\n"));
bcopy(mtod(mprot, uint8_t *), (uint8_t *)rts,
mprot->m_pkthdr.len);
m_freem(mprot);
macctl |= BWN_TX_MAC_SEND_RTSCTS;
len = sizeof(struct ieee80211_frame_rts);
}

View File

@ -1594,38 +1594,18 @@ rt2560_sendprot(struct rt2560_softc *sc,
const struct mbuf *m, struct ieee80211_node *ni, int prot, int rate)
{
struct ieee80211com *ic = ni->ni_ic;
const struct ieee80211_frame *wh;
struct rt2560_tx_desc *desc;
struct rt2560_tx_data *data;
struct mbuf *mprot;
int protrate, ackrate, pktlen, flags, isshort, error;
uint16_t dur;
int protrate, flags, error;
bus_dma_segment_t segs[RT2560_MAX_SCATTER];
int nsegs;
KASSERT(prot == IEEE80211_PROT_RTSCTS || prot == IEEE80211_PROT_CTSONLY,
("protection %d", prot));
wh = mtod(m, const struct ieee80211_frame *);
pktlen = m->m_pkthdr.len + IEEE80211_CRC_LEN;
protrate = ieee80211_ctl_rate(ic->ic_rt, rate);
ackrate = ieee80211_ack_rate(ic->ic_rt, rate);
isshort = (ic->ic_flags & IEEE80211_F_SHPREAMBLE) != 0;
dur = ieee80211_compute_duration(ic->ic_rt, pktlen, rate, isshort)
+ ieee80211_ack_duration(ic->ic_rt, rate, isshort);
flags = RT2560_TX_MORE_FRAG;
if (prot == IEEE80211_PROT_RTSCTS) {
/* NB: CTS is the same size as an ACK */
dur += ieee80211_ack_duration(ic->ic_rt, rate, isshort);
flags |= RT2560_TX_ACK;
mprot = ieee80211_alloc_rts(ic, wh->i_addr1, wh->i_addr2, dur);
} else {
mprot = ieee80211_alloc_cts(ic, ni->ni_vap->iv_myaddr, dur);
}
mprot = ieee80211_alloc_prot(ni, m, rate, prot);
if (mprot == NULL) {
/* XXX stat + msg */
if_inc_counter(ni->ni_vap->iv_ifp, IFCOUNTER_OERRORS, 1);
device_printf(sc->sc_dev,
"could not allocate mbuf for protection mode %d\n", prot);
return ENOBUFS;
}
@ -1646,6 +1626,11 @@ rt2560_sendprot(struct rt2560_softc *sc,
/* ctl frames are not taken into account for amrr */
data->rix = IEEE80211_FIXED_RATE_NONE;
protrate = ieee80211_ctl_rate(ic->ic_rt, rate);
flags = RT2560_TX_MORE_FRAG;
if (prot == IEEE80211_PROT_RTSCTS)
flags |= RT2560_TX_ACK;
rt2560_setup_tx_desc(sc, desc, flags, mprot->m_pkthdr.len, protrate, 1,
segs->ds_addr);

View File

@ -1361,38 +1361,18 @@ rt2661_sendprot(struct rt2661_softc *sc, int ac,
{
struct ieee80211com *ic = ni->ni_ic;
struct rt2661_tx_ring *txq = &sc->txq[ac];
const struct ieee80211_frame *wh;
struct rt2661_tx_desc *desc;
struct rt2661_tx_data *data;
struct mbuf *mprot;
int protrate, ackrate, pktlen, flags, isshort, error;
uint16_t dur;
int protrate, flags, error;
bus_dma_segment_t segs[RT2661_MAX_SCATTER];
int nsegs;
KASSERT(prot == IEEE80211_PROT_RTSCTS || prot == IEEE80211_PROT_CTSONLY,
("protection %d", prot));
wh = mtod(m, const struct ieee80211_frame *);
pktlen = m->m_pkthdr.len + IEEE80211_CRC_LEN;
protrate = ieee80211_ctl_rate(ic->ic_rt, rate);
ackrate = ieee80211_ack_rate(ic->ic_rt, rate);
isshort = (ic->ic_flags & IEEE80211_F_SHPREAMBLE) != 0;
dur = ieee80211_compute_duration(ic->ic_rt, pktlen, rate, isshort)
+ ieee80211_ack_duration(ic->ic_rt, rate, isshort);
flags = RT2661_TX_MORE_FRAG;
if (prot == IEEE80211_PROT_RTSCTS) {
/* NB: CTS is the same size as an ACK */
dur += ieee80211_ack_duration(ic->ic_rt, rate, isshort);
flags |= RT2661_TX_NEED_ACK;
mprot = ieee80211_alloc_rts(ic, wh->i_addr1, wh->i_addr2, dur);
} else {
mprot = ieee80211_alloc_cts(ic, ni->ni_vap->iv_myaddr, dur);
}
mprot = ieee80211_alloc_prot(ni, m, rate, prot);
if (mprot == NULL) {
/* XXX stat + msg */
if_inc_counter(ni->ni_vap->iv_ifp, IFCOUNTER_OERRORS, 1);
device_printf(sc->sc_dev,
"could not allocate mbuf for protection mode %d\n", prot);
return ENOBUFS;
}
@ -1413,6 +1393,11 @@ rt2661_sendprot(struct rt2661_softc *sc, int ac,
/* ctl frames are not taken into account for amrr */
data->rix = IEEE80211_FIXED_RATE_NONE;
protrate = ieee80211_ctl_rate(ic->ic_rt, rate);
flags = RT2661_TX_MORE_FRAG;
if (prot == IEEE80211_PROT_RTSCTS)
flags |= RT2661_TX_NEED_ACK;
rt2661_setup_tx_desc(sc, desc, flags, 0, mprot->m_pkthdr.len,
protrate, segs, 1, ac);

View File

@ -1419,37 +1419,25 @@ rum_sendprot(struct rum_softc *sc,
const struct mbuf *m, struct ieee80211_node *ni, int prot, int rate)
{
struct ieee80211com *ic = ni->ni_ic;
const struct ieee80211_frame *wh;
struct rum_tx_data *data;
struct mbuf *mprot;
int protrate, pktlen, flags, isshort;
uint16_t dur;
int protrate, flags;
RUM_LOCK_ASSERT(sc);
KASSERT(prot == IEEE80211_PROT_RTSCTS || prot == IEEE80211_PROT_CTSONLY,
("protection %d", prot));
wh = mtod(m, const struct ieee80211_frame *);
pktlen = m->m_pkthdr.len + IEEE80211_CRC_LEN;
protrate = ieee80211_ctl_rate(ic->ic_rt, rate);
isshort = (ic->ic_flags & IEEE80211_F_SHPREAMBLE) != 0;
dur = ieee80211_compute_duration(ic->ic_rt, pktlen, rate, isshort)
+ ieee80211_ack_duration(ic->ic_rt, rate, isshort);
flags = 0;
if (prot == IEEE80211_PROT_RTSCTS) {
/* NB: CTS is the same size as an ACK */
dur += ieee80211_ack_duration(ic->ic_rt, rate, isshort);
flags |= RT2573_TX_NEED_ACK;
mprot = ieee80211_alloc_rts(ic, wh->i_addr1, wh->i_addr2, dur);
} else {
mprot = ieee80211_alloc_cts(ic, ni->ni_vap->iv_myaddr, dur);
}
mprot = ieee80211_alloc_prot(ni, m, rate, prot);
if (mprot == NULL) {
/* XXX stat + msg */
if_inc_counter(ni->ni_vap->iv_ifp, IFCOUNTER_OERRORS, 1);
device_printf(sc->sc_dev,
"could not allocate mbuf for protection mode %d\n", prot);
return (ENOBUFS);
}
protrate = ieee80211_ctl_rate(ic->ic_rt, rate);
flags = 0;
if (prot == IEEE80211_PROT_RTSCTS)
flags |= RT2573_TX_NEED_ACK;
data = STAILQ_FIRST(&sc->tx_free);
STAILQ_REMOVE_HEAD(&sc->tx_free, next);
sc->tx_nfree--;

View File

@ -3543,57 +3543,35 @@ run_sendprot(struct run_softc *sc,
const struct mbuf *m, struct ieee80211_node *ni, int prot, int rate)
{
struct ieee80211com *ic = ni->ni_ic;
struct ieee80211_frame *wh;
struct run_tx_data *data;
struct rt2870_txd *txd;
struct rt2860_txwi *txwi;
struct mbuf *mprot;
int ridx;
int protrate;
int ackrate;
int pktlen;
int isshort;
uint16_t dur;
uint8_t type;
uint8_t wflags = 0;
uint8_t xflags = 0;
RUN_LOCK_ASSERT(sc, MA_OWNED);
KASSERT(prot == IEEE80211_PROT_RTSCTS || prot == IEEE80211_PROT_CTSONLY,
("protection %d", prot));
wh = mtod(m, struct ieee80211_frame *);
pktlen = m->m_pkthdr.len + IEEE80211_CRC_LEN;
type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
protrate = ieee80211_ctl_rate(ic->ic_rt, rate);
ackrate = ieee80211_ack_rate(ic->ic_rt, rate);
isshort = (ic->ic_flags & IEEE80211_F_SHPREAMBLE) != 0;
dur = ieee80211_compute_duration(ic->ic_rt, pktlen, rate, isshort)
+ ieee80211_ack_duration(ic->ic_rt, rate, isshort);
wflags = RT2860_TX_FRAG;
/* check that there are free slots before allocating the mbuf */
if (sc->sc_epq[0].tx_nfree == 0)
/* let caller free mbuf */
return (ENOBUFS);
if (prot == IEEE80211_PROT_RTSCTS) {
/* NB: CTS is the same size as an ACK */
dur += ieee80211_ack_duration(ic->ic_rt, rate, isshort);
xflags |= RT2860_TX_ACK;
mprot = ieee80211_alloc_rts(ic, wh->i_addr1, wh->i_addr2, dur);
} else {
mprot = ieee80211_alloc_cts(ic, ni->ni_vap->iv_myaddr, dur);
}
mprot = ieee80211_alloc_prot(ni, m, rate, prot);
if (mprot == NULL) {
if_inc_counter(ni->ni_vap->iv_ifp, IFCOUNTER_OERRORS, 1);
RUN_DPRINTF(sc, RUN_DEBUG_XMIT, "could not allocate mbuf\n");
return (ENOBUFS);
}
protrate = ieee80211_ctl_rate(ic->ic_rt, rate);
wflags = RT2860_TX_FRAG;
xflags = 0;
if (prot == IEEE80211_PROT_RTSCTS)
xflags |= RT2860_TX_ACK;
data = STAILQ_FIRST(&sc->sc_epq[0].tx_fh);
STAILQ_REMOVE_HEAD(&sc->sc_epq[0].tx_fh, next);
sc->sc_epq[0].tx_nfree--;

View File

@ -1130,37 +1130,23 @@ ural_sendprot(struct ural_softc *sc,
const struct mbuf *m, struct ieee80211_node *ni, int prot, int rate)
{
struct ieee80211com *ic = ni->ni_ic;
const struct ieee80211_frame *wh;
struct ural_tx_data *data;
struct mbuf *mprot;
int protrate, ackrate, pktlen, flags, isshort;
uint16_t dur;
int protrate, flags;
KASSERT(prot == IEEE80211_PROT_RTSCTS || prot == IEEE80211_PROT_CTSONLY,
("protection %d", prot));
wh = mtod(m, const struct ieee80211_frame *);
pktlen = m->m_pkthdr.len + IEEE80211_CRC_LEN;
protrate = ieee80211_ctl_rate(ic->ic_rt, rate);
ackrate = ieee80211_ack_rate(ic->ic_rt, rate);
isshort = (ic->ic_flags & IEEE80211_F_SHPREAMBLE) != 0;
dur = ieee80211_compute_duration(ic->ic_rt, pktlen, rate, isshort)
+ ieee80211_ack_duration(ic->ic_rt, rate, isshort);
flags = RAL_TX_RETRY(7);
if (prot == IEEE80211_PROT_RTSCTS) {
/* NB: CTS is the same size as an ACK */
dur += ieee80211_ack_duration(ic->ic_rt, rate, isshort);
flags |= RAL_TX_ACK;
mprot = ieee80211_alloc_rts(ic, wh->i_addr1, wh->i_addr2, dur);
} else {
mprot = ieee80211_alloc_cts(ic, ni->ni_vap->iv_myaddr, dur);
}
mprot = ieee80211_alloc_prot(ni, m, rate, prot);
if (mprot == NULL) {
/* XXX stat + msg */
if_inc_counter(ni->ni_vap->iv_ifp, IFCOUNTER_OERRORS, 1);
device_printf(sc->sc_dev,
"could not allocate mbuf for protection mode %d\n", prot);
return ENOBUFS;
}
protrate = ieee80211_ctl_rate(ic->ic_rt, rate);
flags = RAL_TX_RETRY(7);
if (prot == IEEE80211_PROT_RTSCTS)
flags |= RAL_TX_ACK;
data = STAILQ_FIRST(&sc->tx_free);
STAILQ_REMOVE_HEAD(&sc->tx_free, next);
sc->tx_nfree--;

View File

@ -3088,6 +3088,39 @@ ieee80211_alloc_cts(struct ieee80211com *ic,
return m;
}
/*
* Wrapper for CTS/RTS frame allocation.
*/
struct mbuf *
ieee80211_alloc_prot(struct ieee80211_node *ni, const struct mbuf *m,
uint8_t rate, int prot)
{
struct ieee80211com *ic = ni->ni_ic;
const struct ieee80211_frame *wh;
struct mbuf *mprot;
uint16_t dur;
int pktlen, isshort;
KASSERT(prot == IEEE80211_PROT_RTSCTS ||
prot == IEEE80211_PROT_CTSONLY,
("wrong protection type %d", prot));
wh = mtod(m, const struct ieee80211_frame *);
pktlen = m->m_pkthdr.len + IEEE80211_CRC_LEN;
isshort = (ic->ic_flags & IEEE80211_F_SHPREAMBLE) != 0;
dur = ieee80211_compute_duration(ic->ic_rt, pktlen, rate, isshort)
+ ieee80211_ack_duration(ic->ic_rt, rate, isshort);
if (prot == IEEE80211_PROT_RTSCTS) {
/* NB: CTS is the same size as an ACK */
dur += ieee80211_ack_duration(ic->ic_rt, rate, isshort);
mprot = ieee80211_alloc_rts(ic, wh->i_addr1, wh->i_addr2, dur);
} else
mprot = ieee80211_alloc_cts(ic, ni->ni_vap->iv_myaddr, dur);
return (mprot);
}
static void
ieee80211_tx_mgt_timeout(void *arg)
{

View File

@ -140,6 +140,8 @@ struct mbuf *ieee80211_alloc_rts(struct ieee80211com *ic,
const uint8_t [IEEE80211_ADDR_LEN], uint16_t);
struct mbuf *ieee80211_alloc_cts(struct ieee80211com *,
const uint8_t [IEEE80211_ADDR_LEN], uint16_t);
struct mbuf *ieee80211_alloc_prot(struct ieee80211_node *,
const struct mbuf *, uint8_t, int);
uint8_t *ieee80211_add_rates(uint8_t *, const struct ieee80211_rateset *);
uint8_t *ieee80211_add_xrates(uint8_t *, const struct ieee80211_rateset *);