Move responsibility for removing padding in the RX path entirely to the driver. This allows it to be done once, and thus avoids extra copying of SKBs.

git-svn-id: http://madwifi-project.org/svn/madwifi/trunk@3713 0192ed92-7a03-0410-a25b-9323aeb14dbd
This commit is contained in:
mentor 2008-06-08 01:43:53 +00:00
parent c47c360b48
commit be5b0e727a
5 changed files with 44 additions and 67 deletions

View File

@ -6320,66 +6320,36 @@ ath_rxbuf_init(struct ath_softc *sc, struct ath_buf *bf)
/* This function calculates the presence of, and then removes any padding /* This function calculates the presence of, and then removes any padding
* bytes between the frame header and frame body, and returns a modified * bytes between the frame header and frame body, and returns a modified
* SKB. If padding is removed and copy_skb is specified, then a new SKB is * SKB. */
* created, otherwise the same SKB is used. static void
* ath_skb_removepad(struct ieee80211com *ic, struct sk_buff *skb)
* NB: MAY ALLOCATE */
static struct sk_buff *
ath_skb_removepad(struct sk_buff *skb, unsigned int copy_skb)
{ {
struct sk_buff *tskb = skb;
struct ieee80211_frame *wh = (struct ieee80211_frame *)skb->data; struct ieee80211_frame *wh = (struct ieee80211_frame *)skb->data;
unsigned int padbytes = 0, headersize = 0; unsigned int padbytes = 0, headersize = 0;
KASSERT(ic->ic_flags & IEEE80211_F_DATAPAD,
("data padding not enabled?"));
/* Only non-control frames have bodies, and hence padding. */ /* Only non-control frames have bodies, and hence padding. */
if (IEEE80211_FRM_HAS_BODY(wh)) { if (IEEE80211_FRM_HAS_BODY(wh)) {
headersize = ieee80211_anyhdrsize(wh); headersize = ieee80211_anyhdrsize(wh);
padbytes = roundup(headersize, 4) - headersize; padbytes = roundup(headersize, 4) - headersize;
if (padbytes > 0) { if (padbytes > 0) {
if (copy_skb) { memmove(skb->data + padbytes, skb->data, headersize);
/* Copy skb and remove HW pad bytes */ skb_pull(skb, padbytes);
tskb = skb_copy(skb, GFP_ATOMIC);
if (tskb == NULL)
return NULL;
ieee80211_skb_copy_noderef(skb, tskb);
}
memmove(tskb->data + padbytes, tskb->data, headersize);
skb_pull(tskb, padbytes);
} }
} }
return tskb;
} }
/* static __inline void
* Add a prism2 header to a received frame and
* dispatch it to capture tools like kismet.
*/
static void
ath_capture(struct net_device *dev, const struct ath_buf *bf, ath_capture(struct net_device *dev, const struct ath_buf *bf,
struct sk_buff *skb, u_int64_t tsf, unsigned int tx) struct sk_buff *skb, u_int64_t tsf, unsigned int tx)
{ {
struct ath_softc *sc = dev->priv; struct ath_softc *sc = dev->priv;
struct ieee80211com *ic = &sc->sc_ic; struct ieee80211com *ic = &sc->sc_ic;
struct sk_buff *tskb = NULL;
KASSERT(ic->ic_flags & IEEE80211_F_DATAPAD, if (sc->sc_nmonvaps > 0)
("data padding not enabled?")); ieee80211_input_monitor(ic, skb, bf, tx, tsf, sc);
if (sc->sc_nmonvaps <= 0)
return;
/* Never copy the SKB, as it is ours on the RX side, and this is the
* last process on the TX side and we only modify our own headers. */
tskb = ath_skb_removepad(skb, !tx /* Copy SKB */);
if (tskb == NULL) {
DPRINTF(sc, ATH_DEBUG_ANY,
"Dropping; ath_skb_removepad failed!\n");
return;
}
ieee80211_input_monitor(ic, tskb, bf, tx, tsf, sc);
if (tskb != skb)
ieee80211_dev_kfree_skb(&tskb);
} }
/* /*
@ -6640,6 +6610,7 @@ rx_accept:
skb_put(skb, len); skb_put(skb, len);
skb->protocol = __constant_htons(ETH_P_CONTROL); skb->protocol = __constant_htons(ETH_P_CONTROL);
ath_skb_removepad(ic, skb);
ath_capture(dev, bf, skb, bf->bf_tsf, 0 /* RX */); ath_capture(dev, bf, skb, bf->bf_tsf, 0 /* RX */);
/* Finished monitor mode handling, now reject error frames /* Finished monitor mode handling, now reject error frames
@ -6684,7 +6655,7 @@ rx_accept:
if (IFF_DUMPPKTS(sc, ATH_DEBUG_RECV)) if (IFF_DUMPPKTS(sc, ATH_DEBUG_RECV))
ieee80211_dump_pkt(ic, skb->data, skb->len, ieee80211_dump_pkt(ic, skb->data, skb->len,
sc->sc_hwmap[rs->rs_rate].ieeerate, sc->sc_hwmap[rs->rs_rate].ieeerate,
rs->rs_rssi); rs->rs_rssi, 0);
{ {
struct ieee80211_frame *wh = struct ieee80211_frame *wh =
@ -7973,7 +7944,7 @@ ath_tx_start(struct net_device *dev, struct ieee80211_node *ni,
if (IFF_DUMPPKTS(sc, ATH_DEBUG_XMIT)) if (IFF_DUMPPKTS(sc, ATH_DEBUG_XMIT))
/* FFXXX: need multi-skb version to dump entire FF */ /* FFXXX: need multi-skb version to dump entire FF */
ieee80211_dump_pkt(ic, skb->data, skb->len, ieee80211_dump_pkt(ic, skb->data, skb->len,
sc->sc_hwmap[txrate].ieeerate, -1); sc->sc_hwmap[txrate].ieeerate, -1, 1);
/* /*
* Determine if a tx interrupt should be generated for * Determine if a tx interrupt should be generated for
@ -8354,11 +8325,12 @@ ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
unsigned int i; unsigned int i;
#endif #endif
/* ath_capture modifies skb data; must be last process /* HW is now finished with the SKB, so it is safe to
* in TX path. */ * remove padding. */
tskb = skb->next; ath_skb_removepad(&sc->sc_ic, skb);
DPRINTF(sc, ATH_DEBUG_TX_PROC, "capture skb %p\n", DPRINTF(sc, ATH_DEBUG_TX_PROC, "capture skb %p\n",
bf->bf_skb); bf->bf_skb);
tskb = skb->next;
ath_capture(sc->sc_dev, bf, skb, bf->bf_tsf, 1 /* TX */); ath_capture(sc->sc_dev, bf, skb, bf->bf_tsf, 1 /* TX */);
skb = tskb; skb = tskb;
@ -8366,9 +8338,10 @@ ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
/* Handle every skb after the first one - these are FF /* Handle every skb after the first one - these are FF
* extra buffers */ * extra buffers */
for (i = 0; i < bf->bf_numdescff; i++) { for (i = 0; i < bf->bf_numdescff; i++) {
tskb = skb->next; ath_skb_removepad(&sc->sc_ic, skb); /* XXX: padding for FF? */
DPRINTF(sc, ATH_DEBUG_TX_PROC, "capture skb %p\n", DPRINTF(sc, ATH_DEBUG_TX_PROC, "capture skb %p\n",
skb); skb);
tskb = skb->next;
ath_capture(sc->sc_dev, bf, skb, bf->bf_tsf, 1 /* TX */); ath_capture(sc->sc_dev, bf, skb, bf->bf_tsf, 1 /* TX */);
skb = tskb; skb = tskb;
} }

View File

@ -207,7 +207,7 @@ ieee80211_input(struct ieee80211vap *vap, struct ieee80211_node *ni_or_null,
#ifdef ATH_SUPERG_FF #ifdef ATH_SUPERG_FF
struct llc *llc; struct llc *llc;
#endif #endif
int hdrspace; int hdrlen;
u_int8_t dir, type = -1, subtype; u_int8_t dir, type = -1, subtype;
u_int8_t *bssid; u_int8_t *bssid;
u_int16_t rxseq; u_int16_t rxseq;
@ -431,11 +431,11 @@ ieee80211_input(struct ieee80211vap *vap, struct ieee80211_node *ni_or_null,
switch (type) { switch (type) {
case IEEE80211_FC0_TYPE_DATA: case IEEE80211_FC0_TYPE_DATA:
hdrspace = ieee80211_hdrspace(ic, wh); hdrlen = ieee80211_hdrsize(wh);
if (skb->len < hdrspace) { if (skb->len < hdrlen) {
IEEE80211_DISCARD(vap, IEEE80211_MSG_ANY, IEEE80211_DISCARD(vap, IEEE80211_MSG_ANY,
wh, "data", "too short: len %u, expecting %u", wh, "data", "too short: len %u, expecting %u",
skb->len, hdrspace); skb->len, hdrlen);
vap->iv_stats.is_rx_tooshort++; vap->iv_stats.is_rx_tooshort++;
goto out; /* XXX */ goto out; /* XXX */
} }
@ -624,7 +624,7 @@ ieee80211_input(struct ieee80211vap *vap, struct ieee80211_node *ni_or_null,
IEEE80211_NODE_STAT(ni, rx_noprivacy); IEEE80211_NODE_STAT(ni, rx_noprivacy);
goto out; goto out;
} }
key = ieee80211_crypto_decap(ni, skb, hdrspace); key = ieee80211_crypto_decap(ni, skb, hdrlen);
if (key == NULL) { if (key == NULL) {
/* NB: stats+msgs handled in crypto_decap */ /* NB: stats+msgs handled in crypto_decap */
IEEE80211_NODE_STAT(ni, rx_wepfail); IEEE80211_NODE_STAT(ni, rx_wepfail);
@ -639,7 +639,7 @@ ieee80211_input(struct ieee80211vap *vap, struct ieee80211_node *ni_or_null,
* Next up, any fragmentation. * Next up, any fragmentation.
*/ */
if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) { if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
skb = ieee80211_defrag(ni, skb, hdrspace); skb = ieee80211_defrag(ni, skb, hdrlen);
if (skb == NULL) { if (skb == NULL) {
/* Fragment dropped or frame not complete yet */ /* Fragment dropped or frame not complete yet */
goto out; goto out;
@ -651,7 +651,7 @@ ieee80211_input(struct ieee80211vap *vap, struct ieee80211_node *ni_or_null,
* Next strip any MSDU crypto bits. * Next strip any MSDU crypto bits.
*/ */
if (key != NULL && if (key != NULL &&
!ieee80211_crypto_demic(vap, key, skb, hdrspace, 0)) { !ieee80211_crypto_demic(vap, key, skb, hdrlen, 0)) {
IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT, IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT,
ni->ni_macaddr, "data", "%s", "demic error"); ni->ni_macaddr, "data", "%s", "demic error");
IEEE80211_NODE_STAT(ni, rx_demicfail); IEEE80211_NODE_STAT(ni, rx_demicfail);
@ -661,7 +661,7 @@ ieee80211_input(struct ieee80211vap *vap, struct ieee80211_node *ni_or_null,
/* /*
* Finally, strip the 802.11 header. * Finally, strip the 802.11 header.
*/ */
skb = ieee80211_decap(vap, skb, hdrspace); skb = ieee80211_decap(vap, skb, hdrlen);
if (skb == NULL) { if (skb == NULL) {
/* don't count Null data frames as errors */ /* don't count Null data frames as errors */
if (subtype == IEEE80211_FC0_SUBTYPE_NODATA) if (subtype == IEEE80211_FC0_SUBTYPE_NODATA)
@ -812,8 +812,8 @@ ieee80211_input(struct ieee80211vap *vap, struct ieee80211_node *ni_or_null,
vap->iv_stats.is_rx_noprivacy++; vap->iv_stats.is_rx_noprivacy++;
goto out; goto out;
} }
hdrspace = ieee80211_hdrspace(ic, wh); hdrlen = ieee80211_hdrsize(wh);
key = ieee80211_crypto_decap(ni, skb, hdrspace); key = ieee80211_crypto_decap(ni, skb, hdrlen);
if (key == NULL) { if (key == NULL) {
/* NB: stats+msgs handled in crypto_decap */ /* NB: stats+msgs handled in crypto_decap */
goto out; goto out;
@ -4245,8 +4245,7 @@ ieee80211_check_mic(struct ieee80211_node *ni, struct sk_buff *skb)
struct ieee80211vap *vap = ni->ni_vap; struct ieee80211vap *vap = ni->ni_vap;
struct ieee80211_frame *wh; struct ieee80211_frame *wh;
struct ieee80211_key *key; struct ieee80211_key *key;
int hdrspace; int hdrlen;
struct ieee80211com *ic = vap->iv_ic;
if (skb->len < sizeof(struct ieee80211_frame_min)) { if (skb->len < sizeof(struct ieee80211_frame_min)) {
IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_ANY, IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_ANY,
@ -4257,13 +4256,13 @@ ieee80211_check_mic(struct ieee80211_node *ni, struct sk_buff *skb)
} }
wh = (struct ieee80211_frame *)skb->data; wh = (struct ieee80211_frame *)skb->data;
hdrspace = ieee80211_hdrspace(ic, wh); hdrlen = ieee80211_hdrsize(wh);
key = ieee80211_crypto_decap(ni, skb, hdrspace); key = ieee80211_crypto_decap(ni, skb, hdrlen);
if (key == NULL) { if (key == NULL) {
/* NB: stats+msgs handled in crypto_decap */ /* NB: stats+msgs handled in crypto_decap */
IEEE80211_NODE_STAT(ni, rx_wepfail); IEEE80211_NODE_STAT(ni, rx_wepfail);
} else if (!ieee80211_crypto_demic(vap, key, skb, hdrspace, 1)) { } else if (!ieee80211_crypto_demic(vap, key, skb, hdrlen, 1)) {
IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT, IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT,
ni->ni_macaddr, "data", "%s", "demic error"); ni->ni_macaddr, "data", "%s", "demic error");
IEEE80211_NODE_STAT(ni, rx_demicfail); IEEE80211_NODE_STAT(ni, rx_demicfail);

View File

@ -224,7 +224,8 @@ ieee80211_pwrsave(struct sk_buff *skb)
ni->ni_stats.ns_psq_drops, IEEE80211_PS_MAX_QUEUE); ni->ni_stats.ns_psq_drops, IEEE80211_PS_MAX_QUEUE);
#ifdef IEEE80211_DEBUG #ifdef IEEE80211_DEBUG
if (ieee80211_msg_dumppkts(vap)) if (ieee80211_msg_dumppkts(vap))
ieee80211_dump_pkt(ni->ni_ic, skb->data, skb->len, -1, -1); ieee80211_dump_pkt(ni->ni_ic, skb->data,
skb->len, -1, -1, 1);
#endif #endif
if (SKB_NI(skb) != NULL) if (SKB_NI(skb) != NULL)
ieee80211_unref_node(&SKB_NI(skb)); ieee80211_unref_node(&SKB_NI(skb));

View File

@ -313,8 +313,8 @@ ieee80211_print_essid(const u_int8_t *essid, int len)
EXPORT_SYMBOL(ieee80211_print_essid); EXPORT_SYMBOL(ieee80211_print_essid);
void void
ieee80211_dump_pkt(struct ieee80211com *ic, ieee80211_dump_pkt(struct ieee80211com *ic, const u_int8_t *buf,
const u_int8_t *buf, int len, int rate, int rssi) int len, int rate, int rssi, int tx)
{ {
const struct ieee80211_frame *wh; const struct ieee80211_frame *wh;
int i; int i;
@ -365,7 +365,10 @@ ieee80211_dump_pkt(struct ieee80211com *ic,
if (wh->i_fc[1] & IEEE80211_FC1_PROT) { if (wh->i_fc[1] & IEEE80211_FC1_PROT) {
int off; int off;
off = ieee80211_anyhdrspace(ic, wh); if (tx)
off = ieee80211_anyhdrspace(ic, wh);
else
off = ieee80211_anyhdrsize(wh);
printk(" Prot. [IV %.02x %.02x %.02x", printk(" Prot. [IV %.02x %.02x %.02x",
buf[off + 0], buf[off + 1], buf[off + 2]); buf[off + 0], buf[off + 1], buf[off + 2]);
if (buf[off + IEEE80211_WEP_IVLEN] & IEEE80211_WEP_EXTIV) if (buf[off + IEEE80211_WEP_IVLEN] & IEEE80211_WEP_EXTIV)

View File

@ -252,7 +252,8 @@ void ieee80211_dturbo_switch(struct ieee80211com *, int);
int ieee80211_new_state(struct ieee80211vap *, enum ieee80211_state, int); int ieee80211_new_state(struct ieee80211vap *, enum ieee80211_state, int);
void ieee80211_print_essid(const u_int8_t *, int); void ieee80211_print_essid(const u_int8_t *, int);
#ifdef IEEE80211_DEBUG #ifdef IEEE80211_DEBUG
void ieee80211_dump_pkt(struct ieee80211com *, const u_int8_t *, int, int, int); void ieee80211_dump_pkt(struct ieee80211com *, const u_int8_t *,
int, int, int, int);
#else #else
#define ieee80211_dump_pkt(...) #define ieee80211_dump_pkt(...)
#endif #endif