blob: dd9795ade473c8c5930b1678fb199b8f4a640ee1 [file] [log] [blame]
From be968a6aeea80dca7661e59e0ab5db32341cadb8 Mon Sep 17 00:00:00 2001
From: Michael-CY Lee <michael-cy.lee@mediatek.com>
Date: Mon, 18 Dec 2023 11:35:34 +0800
Subject: [PATCH 2/2] hostapd: mtk: add support for enable/disable single BSS
Enabling or disabling single BSS mean that the beacon of the BSS is
enabled or disabled.
When the BSS is disabled, the following statements are true:
1. the events or packets from the driver are all ignored.
2. Per radio functions (ex. channel switch, color change) will not
execute for the BSS, but are finished by other enabling BSS(es).
The changed parameters take effect when the BSS is enabled again.
3. Enabling the BSS will not reload the configuration. In other word,
if the configuration changes during the BSS disabling, the BSS needs
to be removed and added again, not just be enabled.
This patch add new commands to enable/disable single BSS:
$ hostapd_cli -i <ifname> enable_bss
$ hostapd_cli -i <ifname> disable_bss
Signed-off-by: Michael-CY Lee <michael-cy.lee@mediatek.com>
---
hostapd/ctrl_iface.c | 26 ++++++++++++++++++++
hostapd/hostapd_cli.c | 18 ++++++++++++++
src/ap/hostapd.c | 39 ++++++++++++++++++++++++++++++
src/ap/hostapd.h | 2 ++
src/drivers/driver_nl80211.c | 11 +++++++++
src/drivers/driver_nl80211_event.c | 6 +++++
6 files changed, 102 insertions(+)
diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
index 650af3b..a980c0b 100644
--- a/hostapd/ctrl_iface.c
+++ b/hostapd/ctrl_iface.c
@@ -1590,6 +1590,16 @@ static int hostapd_ctrl_iface_get(struct hostapd_data *hapd, char *cmd,
}
+static int hostapd_ctrl_iface_enable_bss(struct hostapd_data *hapd)
+{
+ if (hostapd_enable_bss(hapd) < 0) {
+ wpa_printf(MSG_ERROR, "Enabling of BSS failed");
+ return -1;
+ }
+ return 0;
+}
+
+
static int hostapd_ctrl_iface_enable(struct hostapd_iface *iface)
{
if (hostapd_enable_iface(iface) < 0) {
@@ -1610,6 +1620,16 @@ static int hostapd_ctrl_iface_reload(struct hostapd_iface *iface)
}
+static int hostapd_ctrl_iface_disable_bss(struct hostapd_data *hapd)
+{
+ if (hostapd_disable_bss(hapd) < 0) {
+ wpa_printf(MSG_ERROR, "Disabling of BSS failed");
+ return -1;
+ }
+ return 0;
+}
+
+
static int hostapd_ctrl_iface_disable(struct hostapd_iface *iface)
{
if (hostapd_disable_iface(iface) < 0) {
@@ -4196,6 +4216,9 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
} else if (os_strncmp(buf, "GET ", 4) == 0) {
reply_len = hostapd_ctrl_iface_get(hapd, buf + 4, reply,
reply_size);
+ } else if (os_strncmp(buf, "ENABLE_BSS", 10) == 0) {
+ if (hostapd_ctrl_iface_enable_bss(hapd))
+ reply_len = -1;
} else if (os_strncmp(buf, "ENABLE", 6) == 0) {
if (hostapd_ctrl_iface_enable(hapd->iface))
reply_len = -1;
@@ -4205,6 +4228,9 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
} else if (os_strncmp(buf, "RELOAD", 6) == 0) {
if (hostapd_ctrl_iface_reload(hapd->iface))
reply_len = -1;
+ } else if (os_strncmp(buf, "DISABLE_BSS", 11) == 0) {
+ if (hostapd_ctrl_iface_disable_bss(hapd))
+ reply_len = -1;
} else if (os_strncmp(buf, "DISABLE", 7) == 0) {
if (hostapd_ctrl_iface_disable(hapd->iface))
reply_len = -1;
diff --git a/hostapd/hostapd_cli.c b/hostapd/hostapd_cli.c
index 0c4a176..c8f0566 100644
--- a/hostapd/hostapd_cli.c
+++ b/hostapd/hostapd_cli.c
@@ -1215,6 +1215,13 @@ static int hostapd_cli_cmd_enable(struct wpa_ctrl *ctrl, int argc,
}
+static int hostapd_cli_cmd_enable_bss(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_ctrl_command(ctrl, "ENABLE_BSS");
+}
+
+
static int hostapd_cli_cmd_reload(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
@@ -1229,6 +1236,13 @@ static int hostapd_cli_cmd_disable(struct wpa_ctrl *ctrl, int argc,
}
+static int hostapd_cli_cmd_disable_bss(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_ctrl_command(ctrl, "DISABLE_BSS");
+}
+
+
static int hostapd_cli_cmd_update_beacon(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
@@ -1731,10 +1745,14 @@ static const struct hostapd_cli_cmd hostapd_cli_commands[] = {
" = send vendor driver command" },
{ "enable", hostapd_cli_cmd_enable, NULL,
"= enable hostapd on current interface" },
+ { "enable_bss", hostapd_cli_cmd_enable_bss, NULL,
+ "= enable hostapd on current BSS" },
{ "reload", hostapd_cli_cmd_reload, NULL,
"= reload configuration for current interface" },
{ "disable", hostapd_cli_cmd_disable, NULL,
"= disable hostapd on current interface" },
+ { "disable_bss", hostapd_cli_cmd_disable_bss, NULL,
+ "= disable hostapd on current BSS" },
{ "update_beacon", hostapd_cli_cmd_update_beacon, NULL,
"= update Beacon frame contents\n"},
{ "erp_flush", hostapd_cli_cmd_erp_flush, NULL,
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
index 7f58354..8b4fc4e 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -3297,6 +3297,42 @@ fail:
}
+int hostapd_enable_bss(struct hostapd_data *hapd)
+{
+ if (hapd->beacon_set_done)
+ return 0;
+
+ if (hapd->conf->bss_load_update_period && bss_load_update_init(hapd)) {
+ wpa_printf(MSG_ERROR, "BSS Load initialization failed");
+ return -1;
+ }
+ return ieee802_11_set_beacon(hapd);
+}
+
+
+int hostapd_disable_bss(struct hostapd_data *hapd)
+{
+ struct hostapd_iface *iface = hapd->iface;
+ int i, remain_bss = 0;
+
+ if (!hapd->beacon_set_done)
+ return 0;
+
+ for (i = 0; i < iface->num_bss; i++)
+ remain_bss += iface->bss[i]->beacon_set_done ? 1 : 0;
+
+ if (remain_bss == 1) {
+ wpa_printf(MSG_ERROR, "Cannot disable last BSS");
+ return -1;
+ }
+
+ hapd->beacon_set_done = 0;
+ bss_load_update_deinit(hapd);
+ hostapd_bss_deinit_no_free(hapd);
+ return hostapd_drv_stop_ap(hapd);
+}
+
+
int hostapd_move_bss_to_first(struct hostapd_iface *iface, int idx)
{
struct hostapd_data *target_hapd, *first_hapd;
@@ -3905,6 +3941,9 @@ int hostapd_switch_channel(struct hostapd_data *hapd,
{
int ret;
+ if (!hapd->beacon_set_done)
+ return 0;
+
if (!(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_AP_CSA)) {
wpa_printf(MSG_INFO, "CSA is not supported");
return -1;
diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h
index 824a24a..88ff1ca 100644
--- a/src/ap/hostapd.h
+++ b/src/ap/hostapd.h
@@ -701,6 +701,8 @@ void hostapd_bss_deinit_no_free(struct hostapd_data *hapd);
void hostapd_free_hapd_data(struct hostapd_data *hapd);
void hostapd_cleanup_iface_partial(struct hostapd_iface *iface);
int hostapd_add_iface(struct hapd_interfaces *ifaces, char *buf);
+int hostapd_enable_bss(struct hostapd_data *hapd);
+int hostapd_disable_bss(struct hostapd_data *hapd);
int hostapd_remove_bss(struct hapd_interfaces *ifaces, char *buf);
int hostapd_remove_iface(struct hapd_interfaces *ifaces, char *buf);
void hostapd_channel_list_updated(struct hostapd_iface *iface, int initiator);
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index cef502f..8e8e194 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -4693,6 +4693,17 @@ static int wpa_driver_nl80211_set_ap(void *priv,
wpa_printf(MSG_DEBUG, "nl80211: dtim_period=%d", params->dtim_period);
wpa_printf(MSG_DEBUG, "nl80211: ssid=%s",
wpa_ssid_txt(params->ssid, params->ssid_len));
+
+ if (!beacon_set) {
+ /* update wdev->preset_chandef in MAC80211 */
+ ret = nl80211_set_channel(bss, params->freq, 1);
+ if (ret) {
+ wpa_printf(MSG_ERROR,
+ "nl80211: Frequency set failed: %d (%s)",
+ ret, strerror(-ret));
+ }
+ }
+
if (!(msg = nl80211_bss_msg(bss, 0, cmd)) ||
nla_put(msg, NL80211_ATTR_BEACON_HEAD, params->head_len,
params->head) ||
diff --git a/src/drivers/driver_nl80211_event.c b/src/drivers/driver_nl80211_event.c
index 585d207..6600c9c 100644
--- a/src/drivers/driver_nl80211_event.c
+++ b/src/drivers/driver_nl80211_event.c
@@ -1094,6 +1094,12 @@ static void mlme_event(struct i802_bss *bss,
return;
}
+ if (is_ap_interface(drv->nlmode) && !bss->beacon_set) {
+ wpa_printf(MSG_DEBUG,
+ "nl80211: drop BSS Event due to disabled BSS");
+ return;
+ }
+
if (frame == NULL) {
wpa_printf(MSG_DEBUG,
"nl80211: MLME event %d (%s) without frame data",
--
2.25.1