Commit 53ad07e9 authored by Johannes Berg's avatar Johannes Berg

wifi: cfg80211: support reporting failed links

For assoc and connect result APIs, support reporting
failed links; they should still come with the BSS
pointer in the case of assoc, so they're released
correctly. In the case of connect result, this is
optional.
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 9b41a9d7
...@@ -6933,6 +6933,8 @@ void cfg80211_auth_timeout(struct net_device *dev, const u8 *addr); ...@@ -6933,6 +6933,8 @@ void cfg80211_auth_timeout(struct net_device *dev, const u8 *addr);
* @ap_mld_addr: AP MLD address (in case of MLO) * @ap_mld_addr: AP MLD address (in case of MLO)
* @links: per-link information indexed by link ID, use links[0] for * @links: per-link information indexed by link ID, use links[0] for
* non-MLO connections * non-MLO connections
* @links.status: Set this (along with a BSS pointer) for links that
* were rejected by the AP.
*/ */
struct cfg80211_rx_assoc_resp { struct cfg80211_rx_assoc_resp {
const u8 *buf; const u8 *buf;
...@@ -6944,6 +6946,7 @@ struct cfg80211_rx_assoc_resp { ...@@ -6944,6 +6946,7 @@ struct cfg80211_rx_assoc_resp {
struct { struct {
const u8 *addr; const u8 *addr;
struct cfg80211_bss *bss; struct cfg80211_bss *bss;
u16 status;
} links[IEEE80211_MLD_MAX_NUM_LINKS]; } links[IEEE80211_MLD_MAX_NUM_LINKS];
}; };
...@@ -7454,6 +7457,9 @@ struct cfg80211_fils_resp_params { ...@@ -7454,6 +7457,9 @@ struct cfg80211_fils_resp_params {
* if the bss is expired during the connection, esp. for those drivers * if the bss is expired during the connection, esp. for those drivers
* implementing connect op. Only one parameter among @bssid and @bss needs * implementing connect op. Only one parameter among @bssid and @bss needs
* to be specified. * to be specified.
* @links.status: per-link status code, to report a status code that's not
* %WLAN_STATUS_SUCCESS for a given link, it must also be in the
* @valid_links bitmap and may have a BSS pointer (which is then released)
*/ */
struct cfg80211_connect_resp_params { struct cfg80211_connect_resp_params {
int status; int status;
...@@ -7470,6 +7476,7 @@ struct cfg80211_connect_resp_params { ...@@ -7470,6 +7476,7 @@ struct cfg80211_connect_resp_params {
const u8 *addr; const u8 *addr;
const u8 *bssid; const u8 *bssid;
struct cfg80211_bss *bss; struct cfg80211_bss *bss;
u16 status;
} links[IEEE80211_MLD_MAX_NUM_LINKS]; } links[IEEE80211_MLD_MAX_NUM_LINKS];
}; };
......
...@@ -42,6 +42,10 @@ void cfg80211_rx_assoc_resp(struct net_device *dev, ...@@ -42,6 +42,10 @@ void cfg80211_rx_assoc_resp(struct net_device *dev,
unsigned int link_id; unsigned int link_id;
for (link_id = 0; link_id < ARRAY_SIZE(data->links); link_id++) { for (link_id = 0; link_id < ARRAY_SIZE(data->links); link_id++) {
cr.links[link_id].status = data->links[link_id].status;
WARN_ON_ONCE(cr.links[link_id].status != WLAN_STATUS_SUCCESS &&
(!cr.ap_mld_addr || !cr.links[link_id].bss));
cr.links[link_id].bss = data->links[link_id].bss; cr.links[link_id].bss = data->links[link_id].bss;
if (!cr.links[link_id].bss) if (!cr.links[link_id].bss)
continue; continue;
......
...@@ -17745,6 +17745,7 @@ void nl80211_send_connect_result(struct cfg80211_registered_device *rdev, ...@@ -17745,6 +17745,7 @@ void nl80211_send_connect_result(struct cfg80211_registered_device *rdev,
link_info_size += (cr->links[link].bssid || link_info_size += (cr->links[link].bssid ||
cr->links[link].bss) ? cr->links[link].bss) ?
nla_total_size(ETH_ALEN) : 0; nla_total_size(ETH_ALEN) : 0;
link_info_size += nla_total_size(sizeof(u16));
} }
} }
...@@ -17813,7 +17814,9 @@ void nl80211_send_connect_result(struct cfg80211_registered_device *rdev, ...@@ -17813,7 +17814,9 @@ void nl80211_send_connect_result(struct cfg80211_registered_device *rdev,
nla_put(msg, NL80211_ATTR_BSSID, ETH_ALEN, bssid)) || nla_put(msg, NL80211_ATTR_BSSID, ETH_ALEN, bssid)) ||
(cr->links[link].addr && (cr->links[link].addr &&
nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN,
cr->links[link].addr))) cr->links[link].addr)) ||
nla_put_u16(msg, NL80211_ATTR_STATUS_CODE,
cr->links[link].status))
goto nla_put_failure; goto nla_put_failure;
nla_nest_end(msg, nested_mlo_links); nla_nest_end(msg, nested_mlo_links);
......
...@@ -793,6 +793,10 @@ void __cfg80211_connect_result(struct net_device *dev, ...@@ -793,6 +793,10 @@ void __cfg80211_connect_result(struct net_device *dev,
} }
for_each_valid_link(cr, link) { for_each_valid_link(cr, link) {
/* don't do extra lookups for failures */
if (cr->links[link].status != WLAN_STATUS_SUCCESS)
continue;
if (cr->links[link].bss) if (cr->links[link].bss)
continue; continue;
...@@ -829,6 +833,16 @@ void __cfg80211_connect_result(struct net_device *dev, ...@@ -829,6 +833,16 @@ void __cfg80211_connect_result(struct net_device *dev,
} }
memset(wdev->links, 0, sizeof(wdev->links)); memset(wdev->links, 0, sizeof(wdev->links));
for_each_valid_link(cr, link) {
if (cr->links[link].status == WLAN_STATUS_SUCCESS)
continue;
cr->valid_links &= ~BIT(link);
/* don't require bss pointer for failed links */
if (!cr->links[link].bss)
continue;
cfg80211_unhold_bss(bss_from_pub(cr->links[link].bss));
cfg80211_put_bss(wdev->wiphy, cr->links[link].bss);
}
wdev->valid_links = cr->valid_links; wdev->valid_links = cr->valid_links;
for_each_valid_link(cr, link) for_each_valid_link(cr, link)
wdev->links[link].client.current_bss = wdev->links[link].client.current_bss =
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment