kfree_skb(skb);
}
-netdev_tx_t ieee80211_subif_start_xmit_8023(struct sk_buff *skb,
- struct net_device *dev)
+static void __ieee80211_subif_start_xmit_8023(struct sk_buff *skb,
+ struct net_device *dev)
{
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
struct ethhdr *ehdr = (struct ethhdr *)skb->data;
struct ieee80211_key *key;
struct sta_info *sta;
- if (unlikely(!ieee80211_sdata_running(sdata) || skb->len < ETH_HLEN)) {
- kfree_skb(skb);
- return NETDEV_TX_OK;
- }
-
rcu_read_lock();
if (ieee80211_lookup_ra_sta(sdata, skb, &sta)) {
ieee80211_subif_start_xmit(skb, dev);
out:
rcu_read_unlock();
+}
+
+netdev_tx_t ieee80211_subif_start_xmit_8023(struct sk_buff *skb,
+ struct net_device *dev)
+{
+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ struct ethhdr *ehdr = (struct ethhdr *)skb->data;
+
+ if (unlikely(!ieee80211_sdata_running(sdata) || skb->len < ETH_HLEN)) {
+ kfree_skb(skb);
+ return NETDEV_TX_OK;
+ }
+
+ if (unlikely(is_multicast_ether_addr(ehdr->h_dest) &&
+ ieee80211_multicast_to_unicast(skb, dev))) {
+ struct sk_buff_head queue;
+
+ __skb_queue_head_init(&queue);
+ ieee80211_convert_to_unicast(skb, dev, &queue);
+ while ((skb = __skb_dequeue(&queue)))
+ __ieee80211_subif_start_xmit_8023(skb, dev);
+ } else {
+ __ieee80211_subif_start_xmit_8023(skb, dev);
+ }
return NETDEV_TX_OK;
}