summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTamizh Chelvam Raja <tamizh.raja@oss.qualcomm.com>2026-06-04 19:24:02 +0300
committerJohannes Berg <johannes.berg@intel.com>2026-06-05 17:09:04 +0300
commit2307b36ce34fd2166509ea2aeef0de5768ed03b7 (patch)
tree4789581e0b7a9cced5942a43a7be3072d79e8972
parent303f11fda2fa4c6f7aa86b8fa54aaee5e1ef181b (diff)
downloadlinux-2307b36ce34fd2166509ea2aeef0de5768ed03b7.tar.xz
wifi: mac80211: Add multicast to unicast support for 802.3 path
mac80211 already supports multicast-to-unicast conversion for native 802.11 TX paths, but this handling is missing for the 802.3 transmit path. Due to that the packet never converted to unicast and directly pass it to 802.11 Tx path by checking the destination address as multicast. Extend ieee80211_subif_start_xmit_8023() to honor the multicast_to_unicast setting by cloning and converting multicast Ethernet frames into per-station unicast transmissions, following the same behavior of the native 802.11 TX path and allow it to take 802.3 path. Signed-off-by: Tamizh Chelvam Raja <tamizh.raja@oss.qualcomm.com> Link: https://patch.msgid.link/20260604162403.1563729-3-tamizh.raja@oss.qualcomm.com Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r--net/mac80211/tx.c33
1 files changed, 26 insertions, 7 deletions
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 15ec77255c3f..a353758f53ff 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -4746,19 +4746,14 @@ out_free:
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)) {
@@ -4787,6 +4782,30 @@ skip_offload:
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;
}