AP MLD: Add support for hostapd_cli to disable/enable AP MLD
Existing commands ENABLE/DISABLE only enable/disable the corresponding link. To disable all links, multiple calls from different control interfaces would be needed. Add new commands "disable_mld" and "enable_mld" for hostapd_cli to support disabling/enabling AP MLD for convenience. Signed-off-by: Chenming Huang <quic_chenhuan@quicinc.com>
This commit is contained in:
parent
0102c5c606
commit
9a47ede871
2 changed files with 122 additions and 0 deletions
|
@ -3457,6 +3457,104 @@ static int hostapd_ctrl_iface_driver_cmd(struct hostapd_data *hapd, char *cmd,
|
||||||
|
|
||||||
|
|
||||||
#ifdef CONFIG_IEEE80211BE
|
#ifdef CONFIG_IEEE80211BE
|
||||||
|
|
||||||
|
static int hostapd_ctrl_iface_enable_mld(struct hostapd_iface *iface)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
if (!iface || !iface->bss[0]->conf->mld_ap) {
|
||||||
|
wpa_printf(MSG_ERROR,
|
||||||
|
"Trying to enable AP MLD on an interface that is not affiliated with an AP MLD");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < iface->interfaces->count; ++i) {
|
||||||
|
struct hostapd_iface *h_iface = iface->interfaces->iface[i];
|
||||||
|
struct hostapd_data *h_hapd = h_iface->bss[0];
|
||||||
|
struct hostapd_bss_config *h_conf = h_hapd->conf;
|
||||||
|
|
||||||
|
if (!h_conf->mld_ap ||
|
||||||
|
h_conf->mld_id != iface->bss[0]->conf->mld_id)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (hostapd_enable_iface(h_iface)) {
|
||||||
|
wpa_printf(MSG_ERROR, "Enabling of AP MLD failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void hostapd_disable_iface_bss(struct hostapd_iface *iface)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
for (i = 0; i < iface->num_bss; i++)
|
||||||
|
hostapd_bss_deinit_no_free(iface->bss[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int hostapd_ctrl_iface_disable_mld(struct hostapd_iface *iface)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
struct hostapd_iface *first_iface = NULL;
|
||||||
|
|
||||||
|
if (!iface || !iface->bss[0]->conf->mld_ap) {
|
||||||
|
wpa_printf(MSG_ERROR,
|
||||||
|
"Trying to disable AP MLD on an interface that is not affiliated with an AP MLD.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* First, disable BSSs before stopping beaconing and doing driver
|
||||||
|
* deinit so that the broadcast Deauthentication frames go out. */
|
||||||
|
|
||||||
|
for (i = 0; i < iface->interfaces->count; ++i) {
|
||||||
|
struct hostapd_iface *h_iface = iface->interfaces->iface[i];
|
||||||
|
struct hostapd_data *h_hapd = h_iface->bss[0];
|
||||||
|
struct hostapd_bss_config *h_conf = h_hapd->conf;
|
||||||
|
|
||||||
|
if (!h_conf->mld_ap ||
|
||||||
|
h_conf->mld_id != iface->bss[0]->conf->mld_id)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!h_hapd->mld_first_bss) {
|
||||||
|
first_iface = h_iface;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
hostapd_disable_iface_bss(iface);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (first_iface)
|
||||||
|
hostapd_disable_iface_bss(first_iface);
|
||||||
|
|
||||||
|
/* Then, fully disable interfaces */
|
||||||
|
|
||||||
|
for (i = 0; i < iface->interfaces->count; ++i) {
|
||||||
|
struct hostapd_iface *h_iface = iface->interfaces->iface[i];
|
||||||
|
struct hostapd_data *h_hapd = h_iface->bss[0];
|
||||||
|
struct hostapd_bss_config *h_conf = h_hapd->conf;
|
||||||
|
|
||||||
|
if (!h_conf->mld_ap ||
|
||||||
|
h_conf->mld_id != iface->bss[0]->conf->mld_id ||
|
||||||
|
!h_hapd->mld_first_bss)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (hostapd_disable_iface(h_iface)) {
|
||||||
|
wpa_printf(MSG_ERROR, "Disabling AP MLD failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (first_iface && hostapd_disable_iface(first_iface)) {
|
||||||
|
wpa_printf(MSG_ERROR, "Disabling AP MLD failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef CONFIG_TESTING_OPTIONS
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
static int hostapd_ctrl_iface_link_remove(struct hostapd_data *hapd, char *cmd,
|
static int hostapd_ctrl_iface_link_remove(struct hostapd_data *hapd, char *cmd,
|
||||||
char *buf, size_t buflen)
|
char *buf, size_t buflen)
|
||||||
|
@ -4044,6 +4142,12 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
|
||||||
reply_size);
|
reply_size);
|
||||||
#endif /* ANDROID */
|
#endif /* ANDROID */
|
||||||
#ifdef CONFIG_IEEE80211BE
|
#ifdef CONFIG_IEEE80211BE
|
||||||
|
} else if (os_strcmp(buf, "ENABLE_MLD") == 0) {
|
||||||
|
if (hostapd_ctrl_iface_enable_mld(hapd->iface))
|
||||||
|
reply_len = -1;
|
||||||
|
} else if (os_strcmp(buf, "DISABLE_MLD") == 0) {
|
||||||
|
if (hostapd_ctrl_iface_disable_mld(hapd->iface))
|
||||||
|
reply_len = -1;
|
||||||
#ifdef CONFIG_TESTING_OPTIONS
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
} else if (os_strncmp(buf, "LINK_REMOVE ", 12) == 0) {
|
} else if (os_strncmp(buf, "LINK_REMOVE ", 12) == 0) {
|
||||||
if (hostapd_ctrl_iface_link_remove(hapd, buf + 12,
|
if (hostapd_ctrl_iface_link_remove(hapd, buf + 12,
|
||||||
|
|
|
@ -1249,6 +1249,20 @@ static int hostapd_cli_cmd_disable(struct wpa_ctrl *ctrl, int argc,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int hostapd_cli_cmd_enable_mld(struct wpa_ctrl *ctrl, int argc,
|
||||||
|
char *argv[])
|
||||||
|
{
|
||||||
|
return wpa_ctrl_command(ctrl, "ENABLE_MLD");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int hostapd_cli_cmd_disable_mld(struct wpa_ctrl *ctrl, int argc,
|
||||||
|
char *argv[])
|
||||||
|
{
|
||||||
|
return wpa_ctrl_command(ctrl, "DISABLE_MLD");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int hostapd_cli_cmd_update_beacon(struct wpa_ctrl *ctrl, int argc,
|
static int hostapd_cli_cmd_update_beacon(struct wpa_ctrl *ctrl, int argc,
|
||||||
char *argv[])
|
char *argv[])
|
||||||
{
|
{
|
||||||
|
@ -1739,6 +1753,10 @@ static const struct hostapd_cli_cmd hostapd_cli_commands[] = {
|
||||||
"= reload configuration for current interface" },
|
"= reload configuration for current interface" },
|
||||||
{ "disable", hostapd_cli_cmd_disable, NULL,
|
{ "disable", hostapd_cli_cmd_disable, NULL,
|
||||||
"= disable hostapd on current interface" },
|
"= disable hostapd on current interface" },
|
||||||
|
{ "enable_mld", hostapd_cli_cmd_enable_mld, NULL,
|
||||||
|
"= enable AP MLD to which the interface is affiliated" },
|
||||||
|
{ "disable_mld", hostapd_cli_cmd_disable_mld, NULL,
|
||||||
|
"= disable AP MLD to which the interface is affiliated" },
|
||||||
{ "update_beacon", hostapd_cli_cmd_update_beacon, NULL,
|
{ "update_beacon", hostapd_cli_cmd_update_beacon, NULL,
|
||||||
"= update Beacon frame contents\n"},
|
"= update Beacon frame contents\n"},
|
||||||
{ "erp_flush", hostapd_cli_cmd_erp_flush, NULL,
|
{ "erp_flush", hostapd_cli_cmd_erp_flush, NULL,
|
||||||
|
|
Loading…
Reference in a new issue