diff options
-rw-r--r-- | include/net/cfg80211.h | 12 | ||||
-rw-r--r-- | net/wireless/nl80211.c | 14 | ||||
-rw-r--r-- | net/wireless/rdev-ops.h | 26 | ||||
-rw-r--r-- | net/wireless/trace.h | 20 |
4 files changed, 70 insertions, 2 deletions
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index a4f9e6094118..5706f96b819a 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -3858,6 +3858,11 @@ struct mgmt_frame_regs { * keep the struct wireless_dev's iftype updated. * This additionally holds the RTNL to be able to do netdev changes. * + * @add_intf_link: Add a new MLO link to the given interface. Note that + * the wdev->link[] data structure has been updated, so the new link + * address is available. + * @del_intf_link: Remove an MLO link from the given interface. + * * @add_key: add a key with the given parameters. @mac_addr will be %NULL * when adding a group key. * @@ -4212,6 +4217,13 @@ struct cfg80211_ops { enum nl80211_iftype type, struct vif_params *params); + int (*add_intf_link)(struct wiphy *wiphy, + struct wireless_dev *wdev, + unsigned int link_id); + void (*del_intf_link)(struct wiphy *wiphy, + struct wireless_dev *wdev, + unsigned int link_id); + int (*add_key)(struct wiphy *wiphy, struct net_device *netdev, u8 key_index, bool pairwise, const u8 *mac_addr, struct key_params *params); diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 9bc66a21ac3a..0a69a5a6b74d 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -15556,9 +15556,11 @@ static int nl80211_set_fils_aad(struct sk_buff *skb, static int nl80211_add_link(struct sk_buff *skb, struct genl_info *info) { + struct cfg80211_registered_device *rdev = info->user_ptr[0]; unsigned int link_id = nl80211_link_id(info->attrs); struct net_device *dev = info->user_ptr[1]; struct wireless_dev *wdev = dev->ieee80211_ptr; + int ret; if (!(wdev->wiphy->flags & WIPHY_FLAG_SUPPORTS_MLO)) return -EINVAL; @@ -15578,13 +15580,20 @@ static int nl80211_add_link(struct sk_buff *skb, struct genl_info *info) wdev->valid_links |= BIT(link_id); ether_addr_copy(wdev->links[link_id].addr, nla_data(info->attrs[NL80211_ATTR_MAC])); + + ret = rdev_add_intf_link(rdev, wdev, link_id); + if (ret) { + wdev->valid_links &= ~BIT(link_id); + eth_zero_addr(wdev->links[link_id].addr); + } wdev_unlock(wdev); - return 0; + return ret; } static int nl80211_remove_link(struct sk_buff *skb, struct genl_info *info) { + struct cfg80211_registered_device *rdev = info->user_ptr[0]; unsigned int link_id = nl80211_link_id(info->attrs); struct net_device *dev = info->user_ptr[1]; struct wireless_dev *wdev = dev->ieee80211_ptr; @@ -15604,6 +15613,9 @@ static int nl80211_remove_link(struct sk_buff *skb, struct genl_info *info) wdev_lock(wdev); wdev->valid_links &= ~BIT(link_id); + + rdev_del_intf_link(rdev, wdev, link_id); + eth_zero_addr(wdev->links[link_id].addr); wdev_unlock(wdev); diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h index d2300eff03ae..a329ba036989 100644 --- a/net/wireless/rdev-ops.h +++ b/net/wireless/rdev-ops.h @@ -1422,4 +1422,30 @@ rdev_set_radar_background(struct cfg80211_registered_device *rdev, return ret; } +static inline int +rdev_add_intf_link(struct cfg80211_registered_device *rdev, + struct wireless_dev *wdev, + unsigned int link_id) +{ + int ret = 0; + + trace_rdev_add_intf_link(&rdev->wiphy, wdev, link_id); + if (rdev->ops->add_intf_link) + ret = rdev->ops->add_intf_link(&rdev->wiphy, wdev, link_id); + trace_rdev_return_int(&rdev->wiphy, ret); + + return ret; +} + +static inline void +rdev_del_intf_link(struct cfg80211_registered_device *rdev, + struct wireless_dev *wdev, + unsigned int link_id) +{ + trace_rdev_del_intf_link(&rdev->wiphy, wdev, link_id); + if (rdev->ops->add_intf_link) + rdev->ops->add_intf_link(&rdev->wiphy, wdev, link_id); + trace_rdev_return_void(&rdev->wiphy); +} + #endif /* __CFG80211_RDEV_OPS */ diff --git a/net/wireless/trace.h b/net/wireless/trace.h index 92742430958e..65f8b814ecd0 100644 --- a/net/wireless/trace.h +++ b/net/wireless/trace.h @@ -2064,7 +2064,7 @@ TRACE_EVENT(rdev_set_noack_map, WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->noack_map) ); -TRACE_EVENT(rdev_get_channel, +DECLARE_EVENT_CLASS(wiphy_wdev_link_evt, TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev, unsigned int link_id), TP_ARGS(wiphy, wdev, link_id), @@ -2082,6 +2082,12 @@ TRACE_EVENT(rdev_get_channel, WIPHY_PR_ARG, WDEV_PR_ARG, __entry->link_id) ); +DEFINE_EVENT(wiphy_wdev_link_evt, rdev_get_channel, + TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev, + unsigned int link_id), + TP_ARGS(wiphy, wdev, link_id) +); + TRACE_EVENT(rdev_return_chandef, TP_PROTO(struct wiphy *wiphy, int ret, struct cfg80211_chan_def *chandef), @@ -2823,6 +2829,18 @@ TRACE_EVENT(rdev_set_radar_background, WIPHY_PR_ARG, CHAN_DEF_PR_ARG) ); +DEFINE_EVENT(wiphy_wdev_link_evt, rdev_add_intf_link, + TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev, + unsigned int link_id), + TP_ARGS(wiphy, wdev, link_id) +); + +DEFINE_EVENT(wiphy_wdev_link_evt, rdev_del_intf_link, + TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev, + unsigned int link_id), + TP_ARGS(wiphy, wdev, link_id) +); + /************************************************************* * cfg80211 exported functions traces * *************************************************************/ |