Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

wifi: cfg80211/mac80211: report link ID for unexpected frames

The upper layer may require the link ID to properly handle
unexpected frames. For instance, if hostapd, operating as an
AP MLD, receives a data frame from a non-associated STA,
it must send deauthentication to the link on which the STA is
operating.

Signed-off-by: Michael-CY Lee <michael-cy.lee@mediatek.com>
Reviewed-by: Money Wang <money.wang@mediatek.com>
Link: https://patch.msgid.link/20250721065159.1740992-1-michael-cy.lee@mediatek.com
[edit commit message]
Signed-off-by: Johannes Berg <johannes.berg@intel.com>

authored by

Michael-CY Lee and committed by
Johannes Berg
84b62b72 4970e393

+33 -26
+6 -4
include/net/cfg80211.h
··· 9048 9048 /** 9049 9049 * cfg80211_rx_spurious_frame - inform userspace about a spurious frame 9050 9050 * @dev: The device the frame matched to 9051 + * @link_id: the link the frame was received on, -1 if not applicable or unknown 9051 9052 * @addr: the transmitter address 9052 9053 * @gfp: context flags 9053 9054 * ··· 9058 9057 * Return: %true if the frame was passed to userspace (or this failed 9059 9058 * for a reason other than not having a subscription.) 9060 9059 */ 9061 - bool cfg80211_rx_spurious_frame(struct net_device *dev, 9062 - const u8 *addr, gfp_t gfp); 9060 + bool cfg80211_rx_spurious_frame(struct net_device *dev, const u8 *addr, 9061 + int link_id, gfp_t gfp); 9063 9062 9064 9063 /** 9065 9064 * cfg80211_rx_unexpected_4addr_frame - inform about unexpected WDS frame 9066 9065 * @dev: The device the frame matched to 9067 9066 * @addr: the transmitter address 9067 + * @link_id: the link the frame was received on, -1 if not applicable or unknown 9068 9068 * @gfp: context flags 9069 9069 * 9070 9070 * This function is used in AP mode (only!) to inform userspace that ··· 9075 9073 * Return: %true if the frame was passed to userspace (or this failed 9076 9074 * for a reason other than not having a subscription.) 9077 9075 */ 9078 - bool cfg80211_rx_unexpected_4addr_frame(struct net_device *dev, 9079 - const u8 *addr, gfp_t gfp); 9076 + bool cfg80211_rx_unexpected_4addr_frame(struct net_device *dev, const u8 *addr, 9077 + int link_id, gfp_t gfp); 9080 9078 9081 9079 /** 9082 9080 * cfg80211_probe_status - notify userspace about probe status
+5 -5
net/mac80211/rx.c
··· 1532 1532 } 1533 1533 1534 1534 if (rx->sdata->vif.type == NL80211_IFTYPE_AP && 1535 - cfg80211_rx_spurious_frame(rx->sdata->dev, 1536 - hdr->addr2, 1537 - GFP_ATOMIC)) 1535 + cfg80211_rx_spurious_frame(rx->sdata->dev, hdr->addr2, 1536 + rx->link_id, GFP_ATOMIC)) 1538 1537 return RX_DROP_U_SPURIOUS; 1539 1538 1540 1539 return RX_DROP; ··· 1871 1872 if (!test_and_set_sta_flag(sta, WLAN_STA_4ADDR_EVENT)) 1872 1873 cfg80211_rx_unexpected_4addr_frame( 1873 1874 rx->sdata->dev, sta->sta.addr, 1874 - GFP_ATOMIC); 1875 + rx->link_id, GFP_ATOMIC); 1875 1876 return RX_DROP_U_UNEXPECTED_4ADDR_FRAME; 1876 1877 } 1877 1878 /* ··· 3190 3191 if (rx->sta && 3191 3192 !test_and_set_sta_flag(rx->sta, WLAN_STA_4ADDR_EVENT)) 3192 3193 cfg80211_rx_unexpected_4addr_frame( 3193 - rx->sdata->dev, rx->sta->sta.addr, GFP_ATOMIC); 3194 + rx->sdata->dev, rx->sta->sta.addr, rx->link_id, 3195 + GFP_ATOMIC); 3194 3196 return RX_DROP; 3195 3197 } 3196 3198
+12 -10
net/wireless/nl80211.c
··· 19755 19755 EXPORT_SYMBOL(cfg80211_conn_failed); 19756 19756 19757 19757 static bool __nl80211_unexpected_frame(struct net_device *dev, u8 cmd, 19758 - const u8 *addr, gfp_t gfp) 19758 + const u8 *addr, int link_id, gfp_t gfp) 19759 19759 { 19760 19760 struct wireless_dev *wdev = dev->ieee80211_ptr; 19761 19761 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); ··· 19778 19778 19779 19779 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || 19780 19780 nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) || 19781 - nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr)) 19781 + nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr) || 19782 + (link_id >= 0 && 19783 + nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID, link_id))) 19782 19784 goto nla_put_failure; 19783 19785 19784 19786 genlmsg_end(msg, hdr); ··· 19792 19790 return true; 19793 19791 } 19794 19792 19795 - bool cfg80211_rx_spurious_frame(struct net_device *dev, 19796 - const u8 *addr, gfp_t gfp) 19793 + bool cfg80211_rx_spurious_frame(struct net_device *dev, const u8 *addr, 19794 + int link_id, gfp_t gfp) 19797 19795 { 19798 19796 struct wireless_dev *wdev = dev->ieee80211_ptr; 19799 19797 bool ret; 19800 19798 19801 - trace_cfg80211_rx_spurious_frame(dev, addr); 19799 + trace_cfg80211_rx_spurious_frame(dev, addr, link_id); 19802 19800 19803 19801 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP && 19804 19802 wdev->iftype != NL80211_IFTYPE_P2P_GO)) { ··· 19806 19804 return false; 19807 19805 } 19808 19806 ret = __nl80211_unexpected_frame(dev, NL80211_CMD_UNEXPECTED_FRAME, 19809 - addr, gfp); 19807 + addr, link_id, gfp); 19810 19808 trace_cfg80211_return_bool(ret); 19811 19809 return ret; 19812 19810 } 19813 19811 EXPORT_SYMBOL(cfg80211_rx_spurious_frame); 19814 19812 19815 - bool cfg80211_rx_unexpected_4addr_frame(struct net_device *dev, 19816 - const u8 *addr, gfp_t gfp) 19813 + bool cfg80211_rx_unexpected_4addr_frame(struct net_device *dev, const u8 *addr, 19814 + int link_id, gfp_t gfp) 19817 19815 { 19818 19816 struct wireless_dev *wdev = dev->ieee80211_ptr; 19819 19817 bool ret; 19820 19818 19821 - trace_cfg80211_rx_unexpected_4addr_frame(dev, addr); 19819 + trace_cfg80211_rx_unexpected_4addr_frame(dev, addr, link_id); 19822 19820 19823 19821 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP && 19824 19822 wdev->iftype != NL80211_IFTYPE_P2P_GO && ··· 19828 19826 } 19829 19827 ret = __nl80211_unexpected_frame(dev, 19830 19828 NL80211_CMD_UNEXPECTED_4ADDR_FRAME, 19831 - addr, gfp); 19829 + addr, link_id, gfp); 19832 19830 trace_cfg80211_return_bool(ret); 19833 19831 return ret; 19834 19832 }
+10 -7
net/wireless/trace.h
··· 3570 3570 ); 3571 3571 3572 3572 DECLARE_EVENT_CLASS(cfg80211_rx_evt, 3573 - TP_PROTO(struct net_device *netdev, const u8 *addr), 3574 - TP_ARGS(netdev, addr), 3573 + TP_PROTO(struct net_device *netdev, const u8 *addr, int link_id), 3574 + TP_ARGS(netdev, addr, link_id), 3575 3575 TP_STRUCT__entry( 3576 3576 NETDEV_ENTRY 3577 3577 MAC_ENTRY(addr) 3578 + __field(int, link_id) 3578 3579 ), 3579 3580 TP_fast_assign( 3580 3581 NETDEV_ASSIGN; 3581 3582 MAC_ASSIGN(addr, addr); 3583 + __entry->link_id = link_id; 3582 3584 ), 3583 - TP_printk(NETDEV_PR_FMT ", %pM", NETDEV_PR_ARG, __entry->addr) 3585 + TP_printk(NETDEV_PR_FMT ", %pM, link_id:%d", NETDEV_PR_ARG, 3586 + __entry->addr, __entry->link_id) 3584 3587 ); 3585 3588 3586 3589 DEFINE_EVENT(cfg80211_rx_evt, cfg80211_rx_spurious_frame, 3587 - TP_PROTO(struct net_device *netdev, const u8 *addr), 3588 - TP_ARGS(netdev, addr) 3590 + TP_PROTO(struct net_device *netdev, const u8 *addr, int link_id), 3591 + TP_ARGS(netdev, addr, link_id) 3589 3592 ); 3590 3593 3591 3594 DEFINE_EVENT(cfg80211_rx_evt, cfg80211_rx_unexpected_4addr_frame, 3592 - TP_PROTO(struct net_device *netdev, const u8 *addr), 3593 - TP_ARGS(netdev, addr) 3595 + TP_PROTO(struct net_device *netdev, const u8 *addr, int link_id), 3596 + TP_ARGS(netdev, addr, link_id) 3594 3597 ); 3595 3598 3596 3599 TRACE_EVENT(cfg80211_ibss_joined,