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
|
/* 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;
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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));
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user