| 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 |
| |