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
* 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
* created, otherwise the same SKB is used.
*
* NB: MAY ALLOCATE */
static struct sk_buff *
ath_skb_removepad(struct sk_buff *skb, unsigned int copy_skb)
* SKB. */
static void
ath_skb_removepad(struct ieee80211com *ic, struct sk_buff *skb)
{
struct sk_buff *tskb = skb;
struct ieee80211_frame *wh = (struct ieee80211_frame *)skb->data;
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. */
if (IEEE80211_FRM_HAS_BODY(wh)) {
headersize = ieee80211_anyhdrsize(wh);
padbytes = roundup(headersize, 4) - headersize;
if (padbytes > 0) {
if (copy_skb) {
/* Copy skb and remove HW pad bytes */
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);
memmove(skb->data + padbytes, skb->data, headersize);
skb_pull(skb, padbytes);
}
}
return tskb;
}
/*
* Add a prism2 header to a received frame and
* dispatch it to capture tools like kismet.
*/
static void
static __inline void
ath_capture(struct net_device *dev, const struct ath_buf *bf,
struct sk_buff *skb, u_int64_t tsf, unsigned int tx)
{
struct ath_softc *sc = dev->priv;
struct ieee80211com *ic = &sc->sc_ic;
struct sk_buff *tskb = NULL;
KASSERT(ic->ic_flags & IEEE80211_F_DATAPAD,
("data padding not enabled?"));
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);
if (sc->sc_nmonvaps > 0)
ieee80211_input_monitor(ic, skb, bf, tx, tsf, sc);
}
/*
@ -6640,6 +6610,7 @@ rx_accept:
skb_put(skb, len);
skb->protocol = __constant_htons(ETH_P_CONTROL);
ath_skb_removepad(ic, skb);
ath_capture(dev, bf, skb, bf->bf_tsf, 0 /* RX */);
/* Finished monitor mode handling, now reject error frames
@ -6684,7 +6655,7 @@ rx_accept:
if (IFF_DUMPPKTS(sc, ATH_DEBUG_RECV))
ieee80211_dump_pkt(ic, skb->data, skb->len,
sc->sc_hwmap[rs->rs_rate].ieeerate,
rs->rs_rssi);
rs->rs_rssi, 0);
{
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))
/* FFXXX: need multi-skb version to dump entire FF */
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
@ -8354,11 +8325,12 @@ ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
unsigned int i;
#endif
/* ath_capture modifies skb data; must be last process
* in TX path. */
tskb = skb->next;
/* HW is now finished with the SKB, so it is safe to
* remove padding. */
ath_skb_removepad(&sc->sc_ic, skb);
DPRINTF(sc, ATH_DEBUG_TX_PROC, "capture skb %p\n",
bf->bf_skb);
tskb = skb->next;
ath_capture(sc->sc_dev, bf, skb, bf->bf_tsf, 1 /* TX */);
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
* extra buffers */
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",
skb);
tskb = skb->next;
ath_capture(sc->sc_dev, bf, skb, bf->bf_tsf, 1 /* TX */);
skb = tskb;
}

View File

@ -207,7 +207,7 @@ ieee80211_input(struct ieee80211vap *vap, struct ieee80211_node *ni_or_null,
#ifdef ATH_SUPERG_FF
struct llc *llc;
#endif
int hdrspace;
int hdrlen;
u_int8_t dir, type = -1, subtype;
u_int8_t *bssid;
u_int16_t rxseq;
@ -431,11 +431,11 @@ ieee80211_input(struct ieee80211vap *vap, struct ieee80211_node *ni_or_null,
switch (type) {
case IEEE80211_FC0_TYPE_DATA:
hdrspace = ieee80211_hdrspace(ic, wh);
if (skb->len < hdrspace) {
hdrlen = ieee80211_hdrsize(wh);
if (skb->len < hdrlen) {
IEEE80211_DISCARD(vap, IEEE80211_MSG_ANY,
wh, "data", "too short: len %u, expecting %u",
skb->len, hdrspace);
skb->len, hdrlen);
vap->iv_stats.is_rx_tooshort++;
goto out; /* XXX */
}
@ -624,7 +624,7 @@ ieee80211_input(struct ieee80211vap *vap, struct ieee80211_node *ni_or_null,
IEEE80211_NODE_STAT(ni, rx_noprivacy);
goto out;
}
key = ieee80211_crypto_decap(ni, skb, hdrspace);
key = ieee80211_crypto_decap(ni, skb, hdrlen);
if (key == NULL) {
/* NB: stats+msgs handled in crypto_decap */
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.
*/
if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
skb = ieee80211_defrag(ni, skb, hdrspace);
skb = ieee80211_defrag(ni, skb, hdrlen);
if (skb == NULL) {
/* Fragment dropped or frame not complete yet */
goto out;
@ -651,7 +651,7 @@ ieee80211_input(struct ieee80211vap *vap, struct ieee80211_node *ni_or_null,
* Next strip any MSDU crypto bits.
*/
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,
ni->ni_macaddr, "data", "%s", "demic error");
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.
*/
skb = ieee80211_decap(vap, skb, hdrspace);
skb = ieee80211_decap(vap, skb, hdrlen);
if (skb == NULL) {
/* don't count Null data frames as errors */
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++;
goto out;
}
hdrspace = ieee80211_hdrspace(ic, wh);
key = ieee80211_crypto_decap(ni, skb, hdrspace);
hdrlen = ieee80211_hdrsize(wh);
key = ieee80211_crypto_decap(ni, skb, hdrlen);
if (key == NULL) {
/* NB: stats+msgs handled in crypto_decap */
goto out;
@ -4245,8 +4245,7 @@ ieee80211_check_mic(struct ieee80211_node *ni, struct sk_buff *skb)
struct ieee80211vap *vap = ni->ni_vap;
struct ieee80211_frame *wh;
struct ieee80211_key *key;
int hdrspace;
struct ieee80211com *ic = vap->iv_ic;
int hdrlen;
if (skb->len < sizeof(struct ieee80211_frame_min)) {
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;
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) {
/* NB: stats+msgs handled in crypto_decap */
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,
ni->ni_macaddr, "data", "%s", "demic error");
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);
#ifdef IEEE80211_DEBUG
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
if (SKB_NI(skb) != NULL)
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);
void
ieee80211_dump_pkt(struct ieee80211com *ic,
const u_int8_t *buf, int len, int rate, int rssi)
ieee80211_dump_pkt(struct ieee80211com *ic, const u_int8_t *buf,
int len, int rate, int rssi, int tx)
{
const struct ieee80211_frame *wh;
int i;
@ -365,7 +365,10 @@ ieee80211_dump_pkt(struct ieee80211com *ic,
if (wh->i_fc[1] & IEEE80211_FC1_PROT) {
int off;
if (tx)
off = ieee80211_anyhdrspace(ic, wh);
else
off = ieee80211_anyhdrsize(wh);
printk(" Prot. [IV %.02x %.02x %.02x",
buf[off + 0], buf[off + 1], buf[off + 2]);
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);
void ieee80211_print_essid(const u_int8_t *, int);
#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
#define ieee80211_dump_pkt(...)
#endif