Skip to content

Commit

Permalink
cfg80211: Indicate MLO links info in connect/roam events
Browse files Browse the repository at this point in the history
Add support for drivers to send MLO links info associated in current
connection in connect and roam cfg80211 callbacks on MLD STA wdev and
send the info to the userspace through corresponding netlink events
from cfg80211.

Signed-off-by: Sunil Dutt <quic_usdutt@quicinc.com>
Co-developed-by: Veerendranath Jakkam <quic_vjakkam@quicinc.com>
Signed-off-by: Veerendranath Jakkam <quic_vjakkam@quicinc.com>
  • Loading branch information
Sunil Dutt authored and intel-lab-lkp committed Feb 22, 2022
1 parent 9bdf523 commit 153c8af
Show file tree
Hide file tree
Showing 8 changed files with 248 additions and 10 deletions.
32 changes: 32 additions & 0 deletions include/net/cfg80211.h
Original file line number Diff line number Diff line change
Expand Up @@ -2735,13 +2735,17 @@ struct cfg80211_auth_request {
* userspace if this flag is set. Only applicable for cfg80211_connect()
* request (connect callback).
* @ASSOC_REQ_DISABLE_HE: Disable HE
* @ASSOC_MLO_SUPPORT: Userspace indicates support for handling MLO links.
* Drivers shall disable MLO features for the current association if this
* flag is not set.
*/
enum cfg80211_assoc_req_flags {
ASSOC_REQ_DISABLE_HT = BIT(0),
ASSOC_REQ_DISABLE_VHT = BIT(1),
ASSOC_REQ_USE_RRM = BIT(2),
CONNECT_REQ_EXTERNAL_AUTH_SUPPORT = BIT(3),
ASSOC_REQ_DISABLE_HE = BIT(4),
ASSOC_MLO_SUPPORT = BIT(5),
};

/**
Expand Down Expand Up @@ -5564,6 +5568,12 @@ static inline void wiphy_unlock(struct wiphy *wiphy)
* @mld_wdev: points to MLD wdev of type %NL80211_IFTYPE_STATION to which this
* MLO link wdev is affiliated to. Valid for iftype
* %NL80211_IFTYPE_MLO_LINK only.
* @link_bssid: BSSID of the AP associated with the MLO link wdev. Valid for
* iftype %NL80211_IFTYPE_MLO_LINK. Scan result of the BSS associated with
* the MLO link may not be available in rdev->bss_list so we can't use
* @current_bss.
* @link_id: AP's MLO link ID to which this non-AP station's MLO link wdev is
* associated. Valid only if iftype is %NL80211_IFTYPE_MLO_LINK.
*/
struct wireless_dev {
struct wiphy *wiphy;
Expand Down Expand Up @@ -5644,6 +5654,8 @@ struct wireless_dev {
unsigned long unprot_beacon_reported;

struct wireless_dev *mld_wdev;
u8 link_bssid[ETH_ALEN];
u8 link_id;
};

static inline const u8 *wdev_address(struct wireless_dev *wdev)
Expand Down Expand Up @@ -7171,6 +7183,18 @@ struct cfg80211_fils_resp_params {
const u8 *pmkid;
};

/**
* struct cfg80211_mlo_link_params - MLO link device params.
* @wdev: the wireless device associated with the MLO link device.
* @bssid: BSSID of the MLO link to which this MLO link is connected to.
* @link_id: Link ID of the AP's MLO link to which this @wdev is connected to.
*/
struct cfg80211_mlo_link_params {
struct wireless_dev *wdev;
u8 bssid[ETH_ALEN];
u8 link_id;
};

/**
* struct cfg80211_connect_resp_params - Connection response params
* @status: Status code, %WLAN_STATUS_SUCCESS for successful connection, use
Expand Down Expand Up @@ -7199,6 +7223,8 @@ struct cfg80211_fils_resp_params {
* not known. This value is used only if @status < 0 to indicate that the
* failure is due to a timeout and not due to explicit rejection by the AP.
* This value is ignored in other cases (@status >= 0).
* @mlo_links: Array of each MLO link's connection parameters.
* @n_mlo_links: Number of valid links that are indicated in @mlo_links.
*/
struct cfg80211_connect_resp_params {
int status;
Expand All @@ -7210,6 +7236,8 @@ struct cfg80211_connect_resp_params {
size_t resp_ie_len;
struct cfg80211_fils_resp_params fils;
enum nl80211_timeout_reason timeout_reason;
const struct cfg80211_mlo_link_params *mlo_links;
int n_mlo_links;
};

/**
Expand Down Expand Up @@ -7359,6 +7387,8 @@ cfg80211_connect_timeout(struct net_device *dev, const u8 *bssid,
* @resp_ie: association response IEs (may be %NULL)
* @resp_ie_len: assoc response IEs length
* @fils: FILS related roaming information.
* @mlo_links: Array of each MLO link's connection parameters.
* @n_mlo_links: Number of valid links that are indicated in @mlo_links.
*/
struct cfg80211_roam_info {
struct ieee80211_channel *channel;
Expand All @@ -7369,6 +7399,8 @@ struct cfg80211_roam_info {
const u8 *resp_ie;
size_t resp_ie_len;
struct cfg80211_fils_resp_params fils;
const struct cfg80211_mlo_link_params *mlo_links;
int n_mlo_links;
};

/**
Expand Down
14 changes: 14 additions & 0 deletions include/uapi/linux/nl80211.h
Original file line number Diff line number Diff line change
Expand Up @@ -2667,7 +2667,15 @@ enum nl80211_commands {
* %NL80211_IFTYPE_STA interface. This is used in
* %NL80211_CMD_GET/SET/NEW_INTERFACE response to indicate information of
* all the MLO links affiliated to %NL80211_IFTYPE_STATION interface.
* This is also used with %NL80211_CMD_CONNECT and %NL80211_CMD_ROAM events
* to indicate associated MLO links information for current connection.
* See &enum nl80211_mlo_link_info_attributes for details.
* @NL80211_ATTR_MLO_SUPPORT: Flag attribute to indicate that the user space
* supports MLO connection. This is used with %NL80211_CMD_CONNECT or
* %NL80211_CMD_ASSOCIATE. The driver shall use MLO link wdevs in
* connection only when userpsace indicates support for MLO connection.
* Using MLO links without userspace support may lead to disconnection
* since RSN connection in MLO needs supplicant support.
*
* @NUM_NL80211_ATTR: total number of nl80211_attrs available
* @NL80211_ATTR_MAX: highest attribute number currently defined
Expand Down Expand Up @@ -3182,6 +3190,7 @@ enum nl80211_attrs {
NL80211_ATTR_EHT_CAPABILITY,

NL80211_ATTR_MLO_LINK_INFO,
NL80211_ATTR_MLO_SUPPORT,

/* add attributes here, update the policy in nl80211.c */

Expand Down Expand Up @@ -7622,6 +7631,9 @@ enum nl80211_ap_settings_flags {
*
* @NL80211_MLO_LINK_INFO_ATTR_WDEV: wireless device identifier for MLO link
* (u64)
* @NL80211_MLO_LINK_INFO_ATTR_BSSID: BSSID associated with this MLO link
* (6 octets).
* @NL80211_MLO_LINK_INFO_ATTR_LINK_ID: link id of associated BSSID (u8)
*
* @__NL80211_MLO_LINK_INFO_ATTR_LAST: Internal
* @NL80211_MLO_LINK_INFO_ATTR_MAX: highest attribute
Expand All @@ -7630,6 +7642,8 @@ enum nl80211_mlo_link_info_attributes {
__NL80211_MLO_LINK_INFO_ATTR_INVALID,

NL80211_MLO_LINK_INFO_ATTR_WDEV,
NL80211_MLO_LINK_INFO_ATTR_BSSID,
NL80211_MLO_LINK_INFO_ATTR_LINK_ID,

/* keep last */
__NL80211_MLO_LINK_INFO_ATTR_LAST,
Expand Down
20 changes: 19 additions & 1 deletion net/wireless/chan.c
Original file line number Diff line number Diff line change
Expand Up @@ -1386,6 +1386,25 @@ cfg80211_get_chan_state(struct wireless_dev *wdev,
return;
}
break;
case NL80211_IFTYPE_MLO_LINK:
if (!is_zero_ether_addr(wdev->link_bssid)) {
if (!memcmp(wdev->link_bssid,
wdev->mld_wdev->current_bss->pub.bssid,
ETH_ALEN))
*chan = wdev->current_bss->pub.channel;
else
*chan = cfg80211_get_colocated_ap_chan(
wiphy_to_rdev(wdev->wiphy),
wdev->mld_wdev->current_bss,
wdev->link_bssid);

if (WARN_ON(!*chan))
return;

*chanmode = CHAN_MODE_SHARED;
return;
}
break;
case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_P2P_GO:
if (wdev->cac_started) {
Expand Down Expand Up @@ -1432,7 +1451,6 @@ cfg80211_get_chan_state(struct wireless_dev *wdev,
return;
case NL80211_IFTYPE_UNSPECIFIED:
case NL80211_IFTYPE_WDS:
case NL80211_IFTYPE_MLO_LINK:
case NUM_NL80211_IFTYPES:
WARN_ON(1);
}
Expand Down
1 change: 1 addition & 0 deletions net/wireless/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -1360,6 +1360,7 @@ void cfg80211_init_wdev(struct wireless_dev *wdev)

INIT_WORK(&wdev->disconnect_wk, cfg80211_autodisconnect_wk);
wdev->mld_wdev = NULL;
eth_zero_addr(wdev->link_bssid);
}

void cfg80211_register_wdev(struct cfg80211_registered_device *rdev,
Expand Down
4 changes: 4 additions & 0 deletions net/wireless/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -579,5 +579,9 @@ void cfg80211_start_mlo_link(struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev);
void cfg80211_stop_mlo_link(struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev);
struct ieee80211_channel *
cfg80211_get_colocated_ap_chan(struct cfg80211_registered_device *rdev,
struct cfg80211_internal_bss *intbss,
const u8 *colocated_bssid);

#endif /* __NET_WIRELESS_CORE_H */
83 changes: 77 additions & 6 deletions net/wireless/nl80211.c
Original file line number Diff line number Diff line change
Expand Up @@ -790,6 +790,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
NLA_POLICY_RANGE(NLA_BINARY,
NL80211_EHT_MIN_CAPABILITY_LEN,
NL80211_EHT_MAX_CAPABILITY_LEN),
[NL80211_ATTR_MLO_SUPPORT] = { .type = NLA_FLAG },
};

/* policy for the key attributes */
Expand Down Expand Up @@ -1499,13 +1500,16 @@ static int nl80211_key_allowed(struct wireless_dev *wdev)
if (!wdev->current_bss)
return -ENOLINK;
break;
case NL80211_IFTYPE_MLO_LINK:
if (is_zero_ether_addr(wdev->link_bssid))
return -ENOLINK;
break;
case NL80211_IFTYPE_UNSPECIFIED:
case NL80211_IFTYPE_OCB:
case NL80211_IFTYPE_MONITOR:
case NL80211_IFTYPE_NAN:
case NL80211_IFTYPE_P2P_DEVICE:
case NL80211_IFTYPE_WDS:
case NL80211_IFTYPE_MLO_LINK:
case NUM_NL80211_IFTYPES:
return -EINVAL;
}
Expand Down Expand Up @@ -3757,6 +3761,13 @@ static int nl80211_send_iface(struct sk_buff *msg, u32 portid, u32 seq, int flag
wdev_id(link_wdev), NL80211_ATTR_PAD))
goto nla_put_failure_locked;

if (!is_zero_ether_addr(link_wdev->link_bssid) &&
(nla_put(msg, NL80211_MLO_LINK_INFO_ATTR_BSSID, ETH_ALEN,
link_wdev->link_bssid) ||
nla_put_u8(msg, NL80211_MLO_LINK_INFO_ATTR_LINK_ID,
link_wdev->link_id)))
goto nla_put_failure_locked;

nla_nest_end(msg, nested_mlo_links);
i++;
}
Expand Down Expand Up @@ -10439,6 +10450,9 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
req.flags |= ASSOC_REQ_USE_RRM;
}

if (nla_get_flag(info->attrs[NL80211_ATTR_MLO_SUPPORT]))
req.flags |= ASSOC_MLO_SUPPORT;

if (info->attrs[NL80211_ATTR_FILS_KEK]) {
req.fils_kek = nla_data(info->attrs[NL80211_ATTR_FILS_KEK]);
req.fils_kek_len = nla_len(info->attrs[NL80211_ATTR_FILS_KEK]);
Expand Down Expand Up @@ -11291,6 +11305,9 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
connect.flags |= CONNECT_REQ_EXTERNAL_AUTH_SUPPORT;
}

if (nla_get_flag(info->attrs[NL80211_ATTR_MLO_SUPPORT]))
connect.flags |= ASSOC_MLO_SUPPORT;

wdev_lock(dev->ieee80211_ptr);

err = cfg80211_connect(rdev, dev, &connect, connkeys,
Expand Down Expand Up @@ -16813,17 +16830,58 @@ void nl80211_send_assoc_timeout(struct cfg80211_registered_device *rdev,
addr, gfp);
}

static int
nl80211_put_mlo_link_params(struct sk_buff *msg,
const struct cfg80211_mlo_link_params *mlo_links,
int n_mlo_links)
{
struct nlattr *nested, *nested_mlo_links;
int i;

if (n_mlo_links) {
nested = nla_nest_start(msg, NL80211_ATTR_MLO_LINK_INFO);
if (!nested)
return -ENOBUFS;

for (i = 0; i < n_mlo_links; i++) {
nested_mlo_links = nla_nest_start(msg, i + 1);
if (!nested_mlo_links)
return -ENOBUFS;

if (nla_put_u64_64bit(msg,
NL80211_MLO_LINK_INFO_ATTR_WDEV,
wdev_id(mlo_links[i].wdev),
NL80211_ATTR_PAD) ||
nla_put(msg, NL80211_MLO_LINK_INFO_ATTR_BSSID,
ETH_ALEN, mlo_links[i].bssid) ||
nla_put_u8(msg, NL80211_MLO_LINK_INFO_ATTR_LINK_ID,
mlo_links[i].link_id))
return -ENOBUFS;

nla_nest_end(msg, nested_mlo_links);
}
nla_nest_end(msg, nested);
}

return 0;
}

void nl80211_send_connect_result(struct cfg80211_registered_device *rdev,
struct net_device *netdev,
struct cfg80211_connect_resp_params *cr,
gfp_t gfp)
{
struct sk_buff *msg;
void *hdr;
int mlo_link_info_size = cr->n_mlo_links *
(nla_total_size_64bit(sizeof(u64)) +
nla_total_size(ETH_ALEN) +
nla_total_size(sizeof(u8)));

msg = nlmsg_new(100 + cr->req_ie_len + cr->resp_ie_len +
cr->fils.kek_len + cr->fils.pmk_len +
(cr->fils.pmkid ? WLAN_PMKID_LEN : 0), gfp);
(cr->fils.pmkid ? WLAN_PMKID_LEN : 0) +
mlo_link_info_size, gfp);
if (!msg)
return;

Expand Down Expand Up @@ -16862,6 +16920,9 @@ void nl80211_send_connect_result(struct cfg80211_registered_device *rdev,
nla_put(msg, NL80211_ATTR_PMKID, WLAN_PMKID_LEN, cr->fils.pmkid)))))
goto nla_put_failure;

if (nl80211_put_mlo_link_params(msg, cr->mlo_links, cr->n_mlo_links))
goto nla_put_failure;

genlmsg_end(msg, hdr);

genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
Expand All @@ -16879,10 +16940,16 @@ void nl80211_send_roamed(struct cfg80211_registered_device *rdev,
struct sk_buff *msg;
void *hdr;
const u8 *bssid = info->bss ? info->bss->bssid : info->bssid;

msg = nlmsg_new(100 + info->req_ie_len + info->resp_ie_len +
info->fils.kek_len + info->fils.pmk_len +
(info->fils.pmkid ? WLAN_PMKID_LEN : 0), gfp);
int mlo_link_info_size = info->n_mlo_links *
(nla_total_size_64bit(sizeof(u64)) +
nla_total_size(ETH_ALEN) +
nla_total_size(sizeof(u8)));

msg = nlmsg_new(100 + info->req_ie_len +
info->resp_ie_len + info->fils.kek_len +
info->fils.pmk_len +
(info->fils.pmkid ? WLAN_PMKID_LEN : 0) +
mlo_link_info_size, gfp);
if (!msg)
return;

Expand Down Expand Up @@ -16913,6 +16980,10 @@ void nl80211_send_roamed(struct cfg80211_registered_device *rdev,
nla_put(msg, NL80211_ATTR_PMKID, WLAN_PMKID_LEN, info->fils.pmkid)))
goto nla_put_failure;

if (nl80211_put_mlo_link_params(msg, info->mlo_links,
info->n_mlo_links))
goto nla_put_failure;

genlmsg_end(msg, hdr);

genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
Expand Down
25 changes: 25 additions & 0 deletions net/wireless/scan.c
Original file line number Diff line number Diff line change
Expand Up @@ -2706,6 +2706,31 @@ void cfg80211_update_assoc_bss_entry(struct wireless_dev *wdev,
spin_unlock_bh(&rdev->bss_lock);
}

struct ieee80211_channel *
cfg80211_get_colocated_ap_chan(struct cfg80211_registered_device *rdev,
struct cfg80211_internal_bss *intbss,
const u8 *colocated_bssid)
{
struct cfg80211_colocated_ap *ap;
LIST_HEAD(coloc_ap_list);
struct cfg80211_bss *res = &intbss->pub;
const struct cfg80211_bss_ies *ies = rcu_access_pointer(res->ies);
struct ieee80211_channel *chan = NULL;

cfg80211_parse_colocated_ap(ies, &coloc_ap_list);

list_for_each_entry(ap, &coloc_ap_list, list) {
if (memcmp(colocated_bssid, ap->bssid, ETH_ALEN))
continue;

chan = ieee80211_get_channel(&rdev->wiphy, ap->center_freq);
break;
}

cfg80211_free_coloc_ap_list(&coloc_ap_list);
return chan;
}

#ifdef CONFIG_CFG80211_WEXT
static struct cfg80211_registered_device *
cfg80211_get_dev_from_ifindex(struct net *net, int ifindex)
Expand Down

0 comments on commit 153c8af

Please sign in to comment.