size_t fils_kek_len;
};
+struct wpa_driver_mld_params {
+ /**
+ * mld_addr - AP's MLD address
+ */
+ const u8 *mld_addr;
+
+ /**
+ * valid_links - The valid links including the association link
+ */
+ u16 valid_links;
+
+ /**
+ * assoc_link_id - The link on which the association is performed
+ */
+ u8 assoc_link_id;
+
+ /**
+ * mld_links - Link information
+ *
+ * Should include information on all the requested links for association
+ * including the link on which the association should take place.
+ * For the association link, the ies and ies_len should be NULL and
+ * 0 respectively.
+ */
+ struct {
+ int freq;
+ const u8 *bssid;
+ const u8 *ies;
+ size_t ies_len;
+ } mld_links[MAX_NUM_MLD_LINKS];
+};
+
/**
* struct wpa_driver_associate_params - Association parameters
* Data for struct wpa_driver_ops::associate().
* disable_eht - Disable EHT for this connection
*/
int disable_eht;
+
+ /*
+ * mld_params - MLD association parameters
+ */
+ struct wpa_driver_mld_params mld_params;
};
enum hide_ssid {
struct wpa_driver_associate_params *params,
struct nl_msg *msg)
{
+ if (params->mld_params.mld_addr && params->mld_params.valid_links > 0) {
+ struct wpa_driver_mld_params *mld_params = ¶ms->mld_params;
+ struct nlattr *links, *attr;
+ int i;
+ u8 link_id;
+
+ wpa_printf(MSG_DEBUG, " * MLD: MLD addr=" MACSTR,
+ MAC2STR(mld_params->mld_addr));
+
+ if (nla_put(msg, NL80211_ATTR_MLD_ADDR, ETH_ALEN,
+ mld_params->mld_addr) ||
+ nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID,
+ mld_params->assoc_link_id))
+ return -1;
+
+ links = nla_nest_start(msg, NL80211_ATTR_MLO_LINKS);
+ if (!links)
+ return -1;
+
+ attr = nla_nest_start(msg, 0);
+ if (!attr)
+ return -1;
+
+ /* First add the association link ID */
+ link_id = mld_params->assoc_link_id;
+ if (nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID, link_id) ||
+ nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN,
+ mld_params->mld_links[link_id].bssid) ||
+ nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ,
+ mld_params->mld_links[link_id].freq))
+ return -1;
+
+ os_memcpy(drv->sta_mlo_info.links[link_id].bssid,
+ mld_params->mld_links[link_id].bssid, ETH_ALEN);
+
+ nla_nest_end(msg, attr);
+
+ for (i = 1, link_id = 0; link_id < MAX_NUM_MLD_LINKS;
+ link_id++) {
+ if (!(mld_params->valid_links & BIT(link_id)) ||
+ link_id == mld_params->assoc_link_id)
+ continue;
+
+ attr = nla_nest_start(msg, i);
+ if (!attr)
+ return -1;
+
+ if (nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID,
+ link_id) ||
+ nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN,
+ mld_params->mld_links[link_id].bssid) ||
+ nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ,
+ mld_params->mld_links[link_id].freq) ||
+ (mld_params->mld_links[link_id].ies &&
+ mld_params->mld_links[i].ies_len &&
+ nla_put(msg, NL80211_ATTR_IE,
+ mld_params->mld_links[link_id].ies_len,
+ mld_params->mld_links[link_id].ies)))
+ return -1;
+
+ os_memcpy(drv->sta_mlo_info.links[link_id].bssid,
+ mld_params->mld_links[link_id].bssid,
+ ETH_ALEN);
+ nla_nest_end(msg, attr);
+ i++;
+ }
+
+ nla_nest_end(msg, links);
+
+ os_memcpy(drv->sta_mlo_info.ap_mld_addr,
+ params->mld_params.mld_addr, ETH_ALEN);
+ drv->sta_mlo_info.assoc_link_id = mld_params->assoc_link_id;
+ drv->sta_mlo_info.req_links = mld_params->valid_links;
+ }
+
if (nla_put_flag(msg, NL80211_ATTR_IFACE_SOCKET_OWNER))
return -1;
- if (params->bssid) {
+ if (params->bssid && !params->mld_params.mld_addr) {
wpa_printf(MSG_DEBUG, " * bssid=" MACSTR,
MAC2STR(params->bssid));
if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, params->bssid))
return -1;
}
- if (params->freq.freq) {
+ if (params->freq.freq && !params->mld_params.mld_addr) {
wpa_printf(MSG_DEBUG, " * freq=%d", params->freq.freq);
if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ,
params->freq.freq))