net80211: separate mbuf cleanup from ieee80211_fragment()
* Create ieee80211_free_mbuf() which frees a list of mbufs. * Use it in the fragment transmit path and ath / uath transmit paths. * Call it in xmit_pkt() if the transmission fails; otherwise fragments may be leaked. This should be a big no-op. Submitted by: <s3erios@gmail.com> Differential Revision: https://reviews.freebsd.org/D3769
This commit is contained in:
parent
5668d203ed
commit
d07be335a0
@ -3262,7 +3262,7 @@ ath_transmit(struct ieee80211com *ic, struct mbuf *m)
|
||||
* XXXGL: is mbuf valid after ath_txfrag_setup? If yes,
|
||||
* we shouldn't free it but return back.
|
||||
*/
|
||||
ath_freetx(m);
|
||||
ieee80211_free_mbuf(m);
|
||||
m = NULL;
|
||||
goto bad;
|
||||
}
|
||||
@ -3356,7 +3356,7 @@ reclaim:
|
||||
__func__,
|
||||
ieee80211_state_name[ni->ni_vap->iv_state]);
|
||||
/* XXX dmamap */
|
||||
ath_freetx(next);
|
||||
ieee80211_free_mbuf(next);
|
||||
goto reclaim;
|
||||
}
|
||||
m = next;
|
||||
|
@ -283,22 +283,6 @@ ath_txfrag_setup(struct ath_softc *sc, ath_bufhead *frags,
|
||||
return !TAILQ_EMPTY(frags);
|
||||
}
|
||||
|
||||
/*
|
||||
* Reclaim mbuf resources. For fragmented frames we
|
||||
* need to claim each frag chained with m_nextpkt.
|
||||
*/
|
||||
void
|
||||
ath_freetx(struct mbuf *m)
|
||||
{
|
||||
struct mbuf *next;
|
||||
|
||||
do {
|
||||
next = m->m_nextpkt;
|
||||
m->m_nextpkt = NULL;
|
||||
m_freem(m);
|
||||
} while ((m = next) != NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
ath_tx_dmasetup(struct ath_softc *sc, struct ath_buf *bf, struct mbuf *m0)
|
||||
{
|
||||
@ -317,7 +301,7 @@ ath_tx_dmasetup(struct ath_softc *sc, struct ath_buf *bf, struct mbuf *m0)
|
||||
bf->bf_nseg = ATH_MAX_SCATTER + 1;
|
||||
} else if (error != 0) {
|
||||
sc->sc_stats.ast_tx_busdma++;
|
||||
ath_freetx(m0);
|
||||
ieee80211_free_mbuf(m0);
|
||||
return error;
|
||||
}
|
||||
/*
|
||||
@ -329,7 +313,7 @@ ath_tx_dmasetup(struct ath_softc *sc, struct ath_buf *bf, struct mbuf *m0)
|
||||
sc->sc_stats.ast_tx_linear++;
|
||||
m = m_collapse(m0, M_NOWAIT, ATH_MAX_SCATTER);
|
||||
if (m == NULL) {
|
||||
ath_freetx(m0);
|
||||
ieee80211_free_mbuf(m0);
|
||||
sc->sc_stats.ast_tx_nombuf++;
|
||||
return ENOMEM;
|
||||
}
|
||||
@ -339,14 +323,14 @@ ath_tx_dmasetup(struct ath_softc *sc, struct ath_buf *bf, struct mbuf *m0)
|
||||
BUS_DMA_NOWAIT);
|
||||
if (error != 0) {
|
||||
sc->sc_stats.ast_tx_busdma++;
|
||||
ath_freetx(m0);
|
||||
ieee80211_free_mbuf(m0);
|
||||
return error;
|
||||
}
|
||||
KASSERT(bf->bf_nseg <= ATH_MAX_SCATTER,
|
||||
("too many segments after defrag; nseg %u", bf->bf_nseg));
|
||||
} else if (bf->bf_nseg == 0) { /* null packet, discard */
|
||||
sc->sc_stats.ast_tx_nodata++;
|
||||
ath_freetx(m0);
|
||||
ieee80211_free_mbuf(m0);
|
||||
return EIO;
|
||||
}
|
||||
DPRINTF(sc, ATH_DEBUG_XMIT, "%s: m %p len %u\n",
|
||||
@ -1581,7 +1565,7 @@ ath_tx_normal_setup(struct ath_softc *sc, struct ieee80211_node *ni,
|
||||
/* Handle encryption twiddling if needed */
|
||||
if (! ath_tx_tag_crypto(sc, ni, m0, iswep, isfrag, &hdrlen,
|
||||
&pktlen, &keyix)) {
|
||||
ath_freetx(m0);
|
||||
ieee80211_free_mbuf(m0);
|
||||
return EIO;
|
||||
}
|
||||
|
||||
@ -1693,7 +1677,7 @@ ath_tx_normal_setup(struct ath_softc *sc, struct ieee80211_node *ni,
|
||||
wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK, __func__);
|
||||
/* XXX statistic */
|
||||
/* XXX free tx dmamap */
|
||||
ath_freetx(m0);
|
||||
ieee80211_free_mbuf(m0);
|
||||
return EIO;
|
||||
}
|
||||
|
||||
@ -1749,7 +1733,7 @@ ath_tx_normal_setup(struct ath_softc *sc, struct ieee80211_node *ni,
|
||||
"%s: discard frame, ACK required w/ TDMA\n", __func__);
|
||||
sc->sc_stats.ast_tdma_ack++;
|
||||
/* XXX free tx dmamap */
|
||||
ath_freetx(m0);
|
||||
ieee80211_free_mbuf(m0);
|
||||
return EIO;
|
||||
}
|
||||
#endif
|
||||
@ -2133,7 +2117,7 @@ ath_tx_raw_start(struct ath_softc *sc, struct ieee80211_node *ni,
|
||||
if (! ath_tx_tag_crypto(sc, ni,
|
||||
m0, params->ibp_flags & IEEE80211_BPF_CRYPTO, 0,
|
||||
&hdrlen, &pktlen, &keyix)) {
|
||||
ath_freetx(m0);
|
||||
ieee80211_free_mbuf(m0);
|
||||
return EIO;
|
||||
}
|
||||
/* packet header may have moved, reset our local pointer */
|
||||
|
@ -85,7 +85,6 @@
|
||||
*/
|
||||
#define ATH_AGGR_MAXSIZE 65530
|
||||
|
||||
extern void ath_freetx(struct mbuf *m);
|
||||
extern void ath_tx_node_flush(struct ath_softc *sc, struct ath_node *an);
|
||||
extern void ath_tx_txq_drain(struct ath_softc *sc, struct ath_txq *txq);
|
||||
extern void ath_txfrag_cleanup(struct ath_softc *sc, ath_bufhead *frags,
|
||||
|
@ -1663,22 +1663,6 @@ uath_txfrag_setup(struct uath_softc *sc, uath_datahead *frags,
|
||||
return !STAILQ_EMPTY(frags);
|
||||
}
|
||||
|
||||
/*
|
||||
* Reclaim mbuf resources. For fragmented frames we need to claim each frag
|
||||
* chained with m_nextpkt.
|
||||
*/
|
||||
static void
|
||||
uath_freetx(struct mbuf *m)
|
||||
{
|
||||
struct mbuf *next;
|
||||
|
||||
do {
|
||||
next = m->m_nextpkt;
|
||||
m->m_nextpkt = NULL;
|
||||
m_freem(m);
|
||||
} while ((m = next) != NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
uath_transmit(struct ieee80211com *ic, struct mbuf *m)
|
||||
{
|
||||
@ -1735,7 +1719,7 @@ uath_start(struct uath_softc *sc)
|
||||
!uath_txfrag_setup(sc, &frags, m, ni)) {
|
||||
DPRINTF(sc, UATH_DEBUG_XMIT,
|
||||
"%s: out of txfrag buffers\n", __func__);
|
||||
uath_freetx(m);
|
||||
ieee80211_free_mbuf(m);
|
||||
goto bad;
|
||||
}
|
||||
sc->sc_seqnum = 0;
|
||||
@ -1770,7 +1754,7 @@ uath_start(struct uath_softc *sc)
|
||||
"%s: flush fragmented packet, state %s\n",
|
||||
__func__,
|
||||
ieee80211_state_name[ni->ni_vap->iv_state]);
|
||||
uath_freetx(next);
|
||||
ieee80211_free_mbuf(next);
|
||||
goto reclaim;
|
||||
}
|
||||
m = next;
|
||||
|
@ -545,7 +545,7 @@ ieee80211_parent_xmitpkt(struct ieee80211com *ic, struct mbuf *m)
|
||||
IEEE80211_TX_LOCK_ASSERT(ic);
|
||||
error = ic->ic_transmit(ic, m);
|
||||
if (error)
|
||||
m_freem(m);
|
||||
ieee80211_free_mbuf(m);
|
||||
return (error);
|
||||
}
|
||||
|
||||
|
@ -1583,6 +1583,21 @@ bad:
|
||||
#undef MC01
|
||||
}
|
||||
|
||||
void
|
||||
ieee80211_free_mbuf(struct mbuf *m)
|
||||
{
|
||||
struct mbuf *next;
|
||||
|
||||
if (m == NULL)
|
||||
return;
|
||||
|
||||
do {
|
||||
next = m->m_nextpkt;
|
||||
m->m_nextpkt = NULL;
|
||||
m_freem(m);
|
||||
} while ((m = next) != NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Fragment the frame according to the specified mtu.
|
||||
* The size of the 802.11 header (w/o padding) is provided
|
||||
@ -1597,7 +1612,7 @@ ieee80211_fragment(struct ieee80211vap *vap, struct mbuf *m0,
|
||||
{
|
||||
struct ieee80211com *ic = vap->iv_ic;
|
||||
struct ieee80211_frame *wh, *whf;
|
||||
struct mbuf *m, *prev, *next;
|
||||
struct mbuf *m, *prev;
|
||||
u_int totalhdrsize, fragno, fragsize, off, remainder, payload;
|
||||
u_int hdrspace;
|
||||
|
||||
@ -1692,11 +1707,7 @@ ieee80211_fragment(struct ieee80211vap *vap, struct mbuf *m0,
|
||||
return 1;
|
||||
bad:
|
||||
/* reclaim fragments but leave original frame for caller to free */
|
||||
for (m = m0->m_nextpkt; m != NULL; m = next) {
|
||||
next = m->m_nextpkt;
|
||||
m->m_nextpkt = NULL; /* XXX paranoid */
|
||||
m_freem(m);
|
||||
}
|
||||
ieee80211_free_mbuf(m0->m_nextpkt);
|
||||
m0->m_nextpkt = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
@ -93,6 +93,7 @@ struct mbuf *ieee80211_mbuf_adjust(struct ieee80211vap *, int,
|
||||
struct ieee80211_key *, struct mbuf *);
|
||||
struct mbuf *ieee80211_encap(struct ieee80211vap *, struct ieee80211_node *,
|
||||
struct mbuf *);
|
||||
void ieee80211_free_mbuf(struct mbuf *);
|
||||
int ieee80211_send_mgmt(struct ieee80211_node *, int, int);
|
||||
struct ieee80211_appie;
|
||||
int ieee80211_send_probereq(struct ieee80211_node *ni,
|
||||
|
Loading…
x
Reference in New Issue
Block a user