mirror of
https://github.com/proski/madwifi
synced 2024-11-25 07:49:43 +03:00
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:
parent
c47c360b48
commit
be5b0e727a
67
ath/if_ath.c
67
ath/if_ath.c
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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));
|
||||
|
@ -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;
|
||||
|
||||
off = ieee80211_anyhdrspace(ic, wh);
|
||||
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)
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user