ieee80211_unref_node(&ni);
} else {
struct ieee80211vap *vap;
+ struct sk_buff *tskb;
/* Create a new SKB copy for each VAP except the last
* one, which gets the original SKB. */
TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
+ if (vap == TAILQ_LAST(&ic->ic_vaps,
+ ieee80211vap_headtype))
+ tskb = skb;
+ else
+ tskb = skb_copy(skb, GFP_ATOMIC);
+
+ if (!tskb)
+ /* XXX: Brilliant OOM handling. */
+ vap->iv_devstats.tx_dropped++;
+ else
type = ieee80211_input(vap, NULL, skb,
rs->rs_rssi, bf->bf_tsf);
}
*/
int
ieee80211_input(struct ieee80211vap * vap, struct ieee80211_node *ni_or_null,
- struct sk_buff *original_skb, int rssi, u_int64_t rtsf)
+ struct sk_buff *skb, int rssi, u_int64_t rtsf)
{
#define HAS_SEQ(type) ((type & 0x4) == 0)
struct ieee80211_node * ni = ni_or_null;
struct ieee80211_frame *wh;
struct ieee80211_key *key;
struct ether_header *eh;
- struct sk_buff *skb = NULL;
#ifdef ATH_SUPERG_FF
struct llc *llc;
#endif
* briefly grab our own reference. */
ni = ieee80211_ref_node(vap->iv_bss);
}
- KASSERT(original_skb != NULL, ("null skb"));
+ KASSERT(skb != NULL, ("null skb"));
KASSERT(ni != NULL, ("null node"));
ni->ni_inact = ni->ni_inact_reload;
type = -1; /* undefined */
* XXX: may want to include the CRC. */
if (vap->iv_opmode == IEEE80211_M_MONITOR)
goto out;
- if (original_skb->len < sizeof(struct ieee80211_frame_min)) {
+ if (skb->len < sizeof(struct ieee80211_frame_min)) {
IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_ANY,
ni->ni_macaddr, NULL,
- "too short (1): len %u", original_skb->len);
+ "too short (1): len %u", skb->len);
vap->iv_stats.is_rx_tooshort++;
goto out;
}
- /* Copy the SKB... we assume somewhere in this driver that we 'own'
- * the skbuff passed into hard start and we do a lot of messing with it
- * but bridges under some cases will not clone for the first pass of skb
- * to a bridge port, but will then clone for subsequent ones. This is
- * odd behavior but it means that if we have trashed the skb we are given
- * then other ports get clones of the residual garbage. */
- if ((skb = skb_copy(original_skb, GFP_ATOMIC)) == NULL) {
- vap->iv_devstats.tx_dropped++;
- original_skb = NULL; /* protect caller's skb */
- goto out;
- }
- ieee80211_skb_copy_noderef(original_skb, skb);
- original_skb = NULL; /* protect caller's skb */
/* Bit of a cheat here, we use a pointer for a 3-address
* frame format but don't reference fields past outside
err:
vap->iv_devstats.rx_errors++;
out:
- if (skb != NULL)
- ieee80211_dev_kfree_skb(&skb); /* This is a copy! */
+ ieee80211_dev_kfree_skb(&skb);
if (ni_or_null == NULL)
ieee80211_unref_node(&ni);
return type;