nl80211: AP MLD support for adding multi link stations
Multi link stations are represented in the kernel using a single station with multiple links and the first ADD_STA command also creates the first link. Subsequent links should be added with LINK_ADD commands. Implement this logic and provide the required MLD information per station/link. Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski@intel.com>
This commit is contained in:
parent
b8b4ceb8d6
commit
df6561ec06
4 changed files with 60 additions and 8 deletions
|
@ -459,6 +459,7 @@ int hostapd_sta_add(struct hostapd_data *hapd,
|
||||||
params.qosinfo = qosinfo;
|
params.qosinfo = qosinfo;
|
||||||
params.support_p2p_ps = supp_p2p_ps;
|
params.support_p2p_ps = supp_p2p_ps;
|
||||||
params.set = set;
|
params.set = set;
|
||||||
|
params.mld_link_id = -1;
|
||||||
return hapd->driver->sta_add(hapd->drv_priv, ¶ms);
|
return hapd->driver->sta_add(hapd->drv_priv, ¶ms);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2403,6 +2403,10 @@ struct hostapd_sta_add_params {
|
||||||
const u8 *supp_oper_classes;
|
const u8 *supp_oper_classes;
|
||||||
size_t supp_oper_classes_len;
|
size_t supp_oper_classes_len;
|
||||||
int support_p2p_ps;
|
int support_p2p_ps;
|
||||||
|
|
||||||
|
bool mld_link_sta;
|
||||||
|
s8 mld_link_id;
|
||||||
|
const u8 *mld_link_addr;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mac_address {
|
struct mac_address {
|
||||||
|
|
|
@ -5285,16 +5285,29 @@ static int wpa_driver_nl80211_sta_add(void *priv,
|
||||||
struct nl_msg *msg;
|
struct nl_msg *msg;
|
||||||
struct nl80211_sta_flag_update upd;
|
struct nl80211_sta_flag_update upd;
|
||||||
int ret = -ENOBUFS;
|
int ret = -ENOBUFS;
|
||||||
|
u8 cmd;
|
||||||
|
const char *cmd_string;
|
||||||
|
|
||||||
if ((params->flags & WPA_STA_TDLS_PEER) &&
|
if ((params->flags & WPA_STA_TDLS_PEER) &&
|
||||||
!(drv->capa.flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT))
|
!(drv->capa.flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT))
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
|
if (params->mld_link_sta) {
|
||||||
|
cmd = params->set ? NL80211_CMD_MODIFY_LINK_STA :
|
||||||
|
NL80211_CMD_ADD_LINK_STA;
|
||||||
|
cmd_string = params->set ? "NL80211_CMD_MODIFY_LINK_STA" :
|
||||||
|
"NL80211_CMD_ADD_LINK_STA";
|
||||||
|
} else {
|
||||||
|
cmd = params->set ? NL80211_CMD_SET_STATION :
|
||||||
|
NL80211_CMD_NEW_STATION;
|
||||||
|
cmd_string = params->set ? "NL80211_CMD_SET_STATION" :
|
||||||
|
"NL80211_CMD_NEW_STATION";
|
||||||
|
}
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "nl80211: %s STA " MACSTR,
|
wpa_printf(MSG_DEBUG, "nl80211: %s STA " MACSTR,
|
||||||
params->set ? "Set" : "Add", MAC2STR(params->addr));
|
cmd_string, MAC2STR(params->addr));
|
||||||
msg = nl80211_bss_msg(bss, 0, params->set ? NL80211_CMD_SET_STATION :
|
msg = nl80211_bss_msg(bss, 0, cmd);
|
||||||
NL80211_CMD_NEW_STATION);
|
if (!msg)
|
||||||
if (!msg || nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, params->addr))
|
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -5512,12 +5525,43 @@ static int wpa_driver_nl80211_sta_add(void *priv,
|
||||||
nla_nest_end(msg, wme);
|
nla_nest_end(msg, wme);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* In case we are an AP MLD need to always specify the link ID */
|
||||||
|
if (params->mld_link_id >= 0) {
|
||||||
|
wpa_printf(MSG_DEBUG, " * mld_link_id=%d",
|
||||||
|
params->mld_link_id);
|
||||||
|
if (nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID,
|
||||||
|
params->mld_link_id))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the link address is specified the station is a non-AP MLD
|
||||||
|
* and thus need to provide the MLD address as the station
|
||||||
|
* address, and the non-AP MLD link address as the link address.
|
||||||
|
*/
|
||||||
|
if (params->mld_link_addr) {
|
||||||
|
wpa_printf(MSG_DEBUG, " * mld_link_addr=" MACSTR,
|
||||||
|
MAC2STR(params->mld_link_addr));
|
||||||
|
|
||||||
|
if (nla_put(msg, NL80211_ATTR_MLD_ADDR,
|
||||||
|
ETH_ALEN, params->addr) ||
|
||||||
|
nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN,
|
||||||
|
params->mld_link_addr))
|
||||||
|
goto fail;
|
||||||
|
} else {
|
||||||
|
if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN,
|
||||||
|
params->addr))
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, params->addr))
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
|
ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
|
||||||
msg = NULL;
|
msg = NULL;
|
||||||
if (ret)
|
if (ret)
|
||||||
wpa_printf(MSG_DEBUG, "nl80211: NL80211_CMD_%s_STATION "
|
wpa_printf(MSG_DEBUG, "nl80211: %s result: %d (%s)",
|
||||||
"result: %d (%s)", params->set ? "SET" : "NEW", ret,
|
cmd_string, ret, strerror(-ret));
|
||||||
strerror(-ret));
|
|
||||||
if (ret == -EEXIST)
|
if (ret == -EEXIST)
|
||||||
ret = 0;
|
ret = 0;
|
||||||
fail:
|
fail:
|
||||||
|
|
|
@ -350,8 +350,11 @@ static inline int wpa_drv_set_ap(struct wpa_supplicant *wpa_s,
|
||||||
static inline int wpa_drv_sta_add(struct wpa_supplicant *wpa_s,
|
static inline int wpa_drv_sta_add(struct wpa_supplicant *wpa_s,
|
||||||
struct hostapd_sta_add_params *params)
|
struct hostapd_sta_add_params *params)
|
||||||
{
|
{
|
||||||
if (wpa_s->driver->sta_add)
|
if (wpa_s->driver->sta_add) {
|
||||||
|
/* Set link_id to -1 as it's needed for AP only */
|
||||||
|
params->mld_link_id = -1;
|
||||||
return wpa_s->driver->sta_add(wpa_s->drv_priv, params);
|
return wpa_s->driver->sta_add(wpa_s->drv_priv, params);
|
||||||
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue