Rewrite ieee80211_input_all()

The logic to prevent calling ieee80211_input() on inactive VAPs was
flawed.  The first VAP was exempt from the check for no reason.

Rewrite to avoid having nested loops.  Give the original skb to the
first VAP, not to the last one, as the first VAP is easier to find in a
loop.  Process the first VAP after others.

Only collect the result from the first VAP.  ieee80211_input() should
return the same value (frame type) for all VAPs except if we call it
incorrectly, e.g. on an inactive VAP.


git-svn-id: http://madwifi-project.org/svn/madwifi/trunk@4081 0192ed92-7a03-0410-a25b-9323aeb14dbd
This commit is contained in:
proski 2009-07-30 21:06:29 +00:00
parent 319a241c30
commit a5b3087ab0
1 changed files with 46 additions and 34 deletions

View File

@ -847,47 +847,59 @@ out:
}
EXPORT_SYMBOL(ieee80211_input);
/*
* Context: softIRQ (tasklet)
*/
int
ieee80211_input_all(struct ieee80211com *ic,
struct sk_buff *skb, int rssi, u_int64_t rtsf)
{
struct ieee80211vap *vap, *next_vap;
struct sk_buff *tskb = NULL;
int type = -1; /* Used to determine when to blinks LEDs. */
/* Create a new SKB copy for each VAP except the last
* one, which gets the original SKB. */
vap = TAILQ_FIRST(&ic->ic_vaps);
while (vap) {
for (next_vap = TAILQ_NEXT(vap, iv_next); next_vap;
next_vap = TAILQ_NEXT(next_vap, iv_next)) {
if ((next_vap->iv_dev->flags & (IFF_RUNNING | IFF_UP))
== (IFF_RUNNING | IFF_UP))
break;
/*
* Deliver a received skb to all VAPs, free the skb.
*
* Context: softIRQ (tasklet)
*/
int
ieee80211_input_all(struct ieee80211com *ic,
struct sk_buff *skb, int rssi, u_int64_t rtsf)
{
struct ieee80211vap *vap, *first_vap = NULL;
int type; /* Used to determine when to blink LEDs. */
for (vap = TAILQ_FIRST(&ic->ic_vaps); vap;
vap = TAILQ_NEXT(vap, iv_next)) {
struct sk_buff *tskb;
/* Check if the interface is up and running */
if ((vap->iv_dev->flags & (IFF_RUNNING | IFF_UP)) !=
(IFF_RUNNING | IFF_UP))
continue;
/* The first VAP will get a special treatment - it will
get the original skb to avoid unneeded skb copying */
if (!first_vap) {
first_vap = vap;
continue;
}
if (!next_vap) {
tskb = skb;
skb = NULL;
} else
tskb = skb_copy(skb, GFP_ATOMIC);
if (!tskb)
/* Other VAPs get a copy of the skb */
tskb = skb_copy(skb, GFP_ATOMIC);
if (!tskb) {
/* XXX: Brilliant OOM handling. */
vap->iv_devstats.tx_dropped++;
else
type = ieee80211_input(vap, NULL, tskb, rssi, rtsf);
continue;
}
ieee80211_input(vap, NULL, tskb, rssi, rtsf);
}
vap = next_vap;
};
/* Process the first VAP now. Any VAP should return a valid type
unless something is very wrong (invalid packet etc). */
if (first_vap)
type = ieee80211_input(first_vap, NULL, skb, rssi, rtsf);
else {
/* No active VAPs, just free the skb */
ieee80211_dev_kfree_skb(&skb);
type = -1;
}
ieee80211_dev_kfree_skb(&skb);
return type;
}
EXPORT_SYMBOL(ieee80211_input_all);
return type;
}
EXPORT_SYMBOL(ieee80211_input_all);
/*
* Determines whether a frame should be accepted, based on information