AP MLD: Link-specific flushing of stations
Whenever a BSS was set up,hostapd flushed all stations via the flush() driver operation which maps to NL80211_CMD_DEL_STATION in the nl80211 interface. However, in case of MLO, a station could have been connected to other links by the time this link is coming up. Since link ID was not passed to flush(), all those stations entries were also removed in the driver which is wrong. Include the link ID along with the command in AP MLD so that the driver can use this link ID and flush only the stations that use the passed link ID as one of their links. Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
This commit is contained in:
parent
5e3c2b489c
commit
b1e463374e
6 changed files with 30 additions and 8 deletions
|
@ -627,9 +627,17 @@ int hostapd_get_seqnum(const char *ifname, struct hostapd_data *hapd,
|
||||||
|
|
||||||
int hostapd_flush(struct hostapd_data *hapd)
|
int hostapd_flush(struct hostapd_data *hapd)
|
||||||
{
|
{
|
||||||
|
int link_id = -1;
|
||||||
|
|
||||||
if (hapd->driver == NULL || hapd->driver->flush == NULL)
|
if (hapd->driver == NULL || hapd->driver->flush == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
return hapd->driver->flush(hapd->drv_priv);
|
|
||||||
|
#ifdef CONFIG_IEEE80211BE
|
||||||
|
if (hapd->conf && hapd->conf->mld_ap)
|
||||||
|
link_id = hapd->mld_link_id;
|
||||||
|
#endif /* CONFIG_IEEE80211BE */
|
||||||
|
|
||||||
|
return hapd->driver->flush(hapd->drv_priv, link_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -3588,13 +3588,15 @@ struct wpa_driver_ops {
|
||||||
/**
|
/**
|
||||||
* flush - Flush all association stations (AP only)
|
* flush - Flush all association stations (AP only)
|
||||||
* @priv: Private driver interface data
|
* @priv: Private driver interface data
|
||||||
|
* @link_id: In case of MLO, valid link ID on which all associated
|
||||||
|
* stations will be flushed, -1 otherwise.
|
||||||
* Returns: 0 on success, -1 on failure
|
* Returns: 0 on success, -1 on failure
|
||||||
*
|
*
|
||||||
* This function requests the driver to disassociate all associated
|
* This function requests the driver to disassociate all associated
|
||||||
* stations. This function does not need to be implemented if the
|
* stations. This function does not need to be implemented if the
|
||||||
* driver does not process association frames internally.
|
* driver does not process association frames internally.
|
||||||
*/
|
*/
|
||||||
int (*flush)(void *priv);
|
int (*flush)(void *priv, int link_id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* set_generic_elem - Add IEs into Beacon/Probe Response frames (AP)
|
* set_generic_elem - Add IEs into Beacon/Probe Response frames (AP)
|
||||||
|
|
|
@ -632,7 +632,7 @@ atheros_get_seqnum(const char *ifname, void *priv, const u8 *addr, int idx,
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
atheros_flush(void *priv)
|
atheros_flush(void *priv, int link_id)
|
||||||
{
|
{
|
||||||
u8 allsta[IEEE80211_ADDR_LEN];
|
u8 allsta[IEEE80211_ADDR_LEN];
|
||||||
os_memset(allsta, 0xff, IEEE80211_ADDR_LEN);
|
os_memset(allsta, 0xff, IEEE80211_ADDR_LEN);
|
||||||
|
|
|
@ -946,7 +946,7 @@ bsd_get_seqnum(const char *ifname, void *priv, const u8 *addr, int idx,
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
bsd_flush(void *priv)
|
bsd_flush(void *priv, int link_id)
|
||||||
{
|
{
|
||||||
u8 allsta[IEEE80211_ADDR_LEN];
|
u8 allsta[IEEE80211_ADDR_LEN];
|
||||||
|
|
||||||
|
|
|
@ -572,7 +572,7 @@ static int hostap_set_ssid(void *priv, const u8 *buf, int len)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int hostap_flush(void *priv)
|
static int hostap_flush(void *priv, int link_id)
|
||||||
{
|
{
|
||||||
struct hostap_driver_data *drv = priv;
|
struct hostap_driver_data *drv = priv;
|
||||||
struct prism2_hostapd_param param;
|
struct prism2_hostapd_param param;
|
||||||
|
|
|
@ -7724,25 +7724,37 @@ static int i802_set_frag(void *priv, int frag)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int i802_flush(void *priv)
|
static int i802_flush(void *priv, int link_id)
|
||||||
{
|
{
|
||||||
struct i802_bss *bss = priv;
|
struct i802_bss *bss = priv;
|
||||||
struct nl_msg *msg;
|
struct nl_msg *msg;
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "nl80211: flush -> DEL_STATION %s (all)",
|
if (link_id == NL80211_DRV_LINK_ID_NA)
|
||||||
bss->ifname);
|
wpa_printf(MSG_DEBUG, "nl80211: flush -> DEL_STATION %s (all)",
|
||||||
|
bss->ifname);
|
||||||
|
else
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"nl80211: flush -> DEL_STATION %s (with link %d)",
|
||||||
|
bss->ifname, link_id);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* XXX: FIX! this needs to flush all VLANs too
|
* XXX: FIX! this needs to flush all VLANs too
|
||||||
*/
|
*/
|
||||||
msg = nl80211_bss_msg(bss, 0, NL80211_CMD_DEL_STATION);
|
msg = nl80211_bss_msg(bss, 0, NL80211_CMD_DEL_STATION);
|
||||||
|
if (link_id >= 0 && (bss->valid_links & BIT(link_id)) &&
|
||||||
|
nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID, link_id))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
res = send_and_recv_cmd(bss->drv, msg);
|
res = send_and_recv_cmd(bss->drv, msg);
|
||||||
if (res) {
|
if (res) {
|
||||||
wpa_printf(MSG_DEBUG, "nl80211: Station flush failed: ret=%d "
|
wpa_printf(MSG_DEBUG, "nl80211: Station flush failed: ret=%d "
|
||||||
"(%s)", res, strerror(-res));
|
"(%s)", res, strerror(-res));
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
|
fail:
|
||||||
|
nlmsg_free(msg);
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue