developer | 05f3b2b | 2024-08-19 19:17:34 +0800 | [diff] [blame^] | 1 | From 288062b9de2d669b809ae7b0035ca4680c358192 Mon Sep 17 00:00:00 2001 |
| 2 | From: Shayne Chen <shayne.chen@mediatek.com> |
| 3 | Date: Thu, 11 Apr 2024 18:16:38 +0800 |
| 4 | Subject: [PATCH 079/126] mtk: hostapd: make sure all links are set before |
| 5 | enabling beacon |
| 6 | |
| 7 | NL80211_CMD_NEW_BEACON will first be set, but we've modified mac80211 to |
| 8 | disable this beacon. After that, hostapd will block |
| 9 | NL80211_CMD_SET_BEACON until all links are setting up. |
| 10 | (use NL80211_CMD_START_AP event to check if all expected links are enabled) |
| 11 | |
| 12 | Update: in wpa_driver_nl80211_set_ap(), send_and_recv() is used, implies |
| 13 | that hostapd should already sync with driver, so don't need to use |
| 14 | NL80211_CMD_START_AP event. |
| 15 | |
| 16 | This can make sure that the first beacon of each link includes the |
| 17 | correct RNR and per-STA profile. |
| 18 | |
| 19 | Note that in NL80211_CMD_NEW_BEACON, we also set beacon interval to 0, |
| 20 | which helps to bypass some mac80211 beacon active checks, e.g., during ACS. |
| 21 | |
| 22 | Add is_mld_finished check for ucode need. |
| 23 | This function returns ture only if all links fromt all MLD APs are |
| 24 | ready. |
| 25 | |
| 26 | Only after hostapd sets beacon for all links that hapd->mld->started is |
| 27 | set to true. However, if the interface is about to do CAC, |
| 28 | hapd->mld->started will be false until the CAC is done. |
| 29 | |
| 30 | For ucode, it only have to ckeck whether all link is added. Instead of |
| 31 | checking hapd->mld->started, this commits check the link one by one, and |
| 32 | return false if there are links unadded. |
| 33 | |
| 34 | Signed-off-by: Shayne Chen <shayne.chen@mediatek.com> |
| 35 | Signed-off-by: Michael-CY Lee <michael-cy.lee@mediatek.com> |
| 36 | --- |
| 37 | hostapd/config_file.c | 2 ++ |
| 38 | src/ap/ap_config.h | 2 ++ |
| 39 | src/ap/beacon.c | 10 ++++++++++ |
| 40 | src/ap/hostapd.c | 14 ++++++++++++++ |
| 41 | src/ap/hostapd.h | 1 + |
| 42 | src/ap/ucode.c | 27 +++++++++++++++++++++++++++ |
| 43 | 6 files changed, 56 insertions(+) |
| 44 | |
| 45 | diff --git a/hostapd/config_file.c b/hostapd/config_file.c |
| 46 | index 44615c564..206055b75 100644 |
| 47 | --- a/hostapd/config_file.c |
| 48 | +++ b/hostapd/config_file.c |
| 49 | @@ -5467,6 +5467,8 @@ static int hostapd_config_fill(struct hostapd_config *conf, |
| 50 | bss->mld_ap = !!atoi(pos); |
| 51 | } else if (os_strcmp(buf, "mld_primary") == 0) { |
| 52 | bss->mld_primary = !!atoi(pos); |
| 53 | + } else if (os_strcmp(buf, "mld_allowed_links") == 0) { |
| 54 | + bss->mld_allowed_links = atoi(pos); |
| 55 | } else if (os_strcmp(buf, "mld_addr") == 0) { |
| 56 | if (hwaddr_aton(pos, bss->mld_addr)) { |
| 57 | wpa_printf(MSG_ERROR, "Line %d: Invalid mld_addr", |
| 58 | diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h |
| 59 | index 417b1d630..15b66ca30 100644 |
| 60 | --- a/src/ap/ap_config.h |
| 61 | +++ b/src/ap/ap_config.h |
| 62 | @@ -989,6 +989,8 @@ struct hostapd_bss_config { |
| 63 | |
| 64 | /* The AP is the primary AP of an AP MLD */ |
| 65 | u8 mld_primary; |
| 66 | + /* Allowed link bitmap of the AP MLD to which the AP is affiliated */ |
| 67 | + u16 mld_allowed_links; |
| 68 | |
| 69 | /* The MLD ID to which the AP MLD is affiliated with */ |
| 70 | u8 mld_id; |
| 71 | diff --git a/src/ap/beacon.c b/src/ap/beacon.c |
| 72 | index 9bf73747f..88e35acc2 100644 |
| 73 | --- a/src/ap/beacon.c |
| 74 | +++ b/src/ap/beacon.c |
| 75 | @@ -2276,6 +2276,12 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd, |
| 76 | os_memcpy(head->bssid, hapd->own_addr, ETH_ALEN); |
| 77 | head->u.beacon.beacon_int = |
| 78 | host_to_le16(hapd->iconf->beacon_int); |
| 79 | + /* if MLD AP hasn't finished setting up all links, also set beacon interval |
| 80 | + * to 0. This allows mac80211 to bypass some beacon active checks, for |
| 81 | + * example, when doing ACS |
| 82 | + */ |
| 83 | + if (hapd->conf->mld_ap && !hapd->mld->started) |
| 84 | + head->u.beacon.beacon_int = host_to_le16(0); |
| 85 | |
| 86 | /* hardware or low-level driver will setup seq_ctrl and timestamp */ |
| 87 | capab_info = hostapd_own_capab_info(hapd); |
| 88 | @@ -2677,6 +2683,10 @@ static int __ieee802_11_set_beacon(struct hostapd_data *hapd) |
| 89 | int res, ret = -1, i; |
| 90 | struct hostapd_hw_modes *mode; |
| 91 | |
| 92 | + /* skip setting beacon if other links are not started yet */ |
| 93 | + if (hapd->conf->mld_ap && !hapd->mld->started && hapd->beacon_set_done) |
| 94 | + return 0; |
| 95 | + |
| 96 | if (!hapd->drv_priv) { |
| 97 | wpa_printf(MSG_ERROR, "Interface is disabled"); |
| 98 | return -1; |
| 99 | diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c |
| 100 | index f5e11d43d..fe41f1821 100644 |
| 101 | --- a/src/ap/hostapd.c |
| 102 | +++ b/src/ap/hostapd.c |
| 103 | @@ -1315,6 +1315,20 @@ static int hostapd_start_beacon(struct hostapd_data *hapd, |
| 104 | if (!conf->start_disabled && ieee802_11_set_beacon(hapd) < 0) |
| 105 | return -1; |
| 106 | |
| 107 | + if (hapd->conf->mld_ap && !hapd->mld->started) { |
| 108 | + struct hostapd_data *p_hapd; |
| 109 | + u16 valid_links = 0; |
| 110 | + |
| 111 | + for_each_mld_link(p_hapd, hapd) |
| 112 | + valid_links |= BIT(p_hapd->mld_link_id); |
| 113 | + |
| 114 | + if (valid_links == hapd->conf->mld_allowed_links || |
| 115 | + !hapd->conf->mld_allowed_links) { |
| 116 | + hapd->mld->started = 1; |
| 117 | + ieee802_11_set_beacon(hapd); |
| 118 | + } |
| 119 | + } |
| 120 | + |
| 121 | if (flush_old_stations && !conf->start_disabled && |
| 122 | conf->broadcast_deauth) { |
| 123 | u8 addr[ETH_ALEN]; |
| 124 | diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h |
| 125 | index 574a5ba1d..4db67096b 100644 |
| 126 | --- a/src/ap/hostapd.h |
| 127 | +++ b/src/ap/hostapd.h |
| 128 | @@ -544,6 +544,7 @@ struct hostapd_mld { |
| 129 | * freed when num_links is 0. |
| 130 | */ |
| 131 | u8 refcount; |
| 132 | + bool started; |
| 133 | |
| 134 | struct hostapd_data *fbss; |
| 135 | struct dl_list links; /* List head of all affiliated links */ |
| 136 | diff --git a/src/ap/ucode.c b/src/ap/ucode.c |
| 137 | index 68f76dbe5..da1c4c1ac 100644 |
| 138 | --- a/src/ap/ucode.c |
| 139 | +++ b/src/ap/ucode.c |
| 140 | @@ -744,6 +744,32 @@ uc_hostapd_iface_switch_channel(uc_vm_t *vm, size_t nargs) |
| 141 | return ucv_boolean_new(!ret); |
| 142 | } |
| 143 | |
| 144 | +static uc_value_t * |
| 145 | +uc_hostapd_iface_is_mld_finished(uc_vm_t *vm, size_t nargs) |
| 146 | +{ |
| 147 | + struct hostapd_iface *iface = uc_fn_thisval("hostapd.iface"); |
| 148 | + bool finished = true; |
| 149 | + int i; |
| 150 | + |
| 151 | + for (i = 0; i < iface->num_bss; i++) { |
| 152 | + if (iface->bss[i]->conf->mld_ap) { |
| 153 | + struct hostapd_data *p_hapd; |
| 154 | + u16 valid_links = 0; |
| 155 | + |
| 156 | + for_each_mld_link(p_hapd, iface->bss[i]) |
| 157 | + valid_links |= BIT(p_hapd->mld_link_id); |
| 158 | + |
| 159 | + if (iface->bss[i]->conf->mld_allowed_links > 0 && |
| 160 | + valid_links != iface->bss[i]->conf->mld_allowed_links) { |
| 161 | + finished = false; |
| 162 | + break; |
| 163 | + } |
| 164 | + } |
| 165 | + } |
| 166 | + |
| 167 | + return ucv_boolean_new(finished); |
| 168 | +} |
| 169 | + |
| 170 | static uc_value_t * |
| 171 | uc_hostapd_bss_rename(uc_vm_t *vm, size_t nargs) |
| 172 | { |
| 173 | @@ -816,6 +842,7 @@ int hostapd_ucode_init(struct hapd_interfaces *ifaces) |
| 174 | { "stop", uc_hostapd_iface_stop }, |
| 175 | { "start", uc_hostapd_iface_start }, |
| 176 | { "switch_channel", uc_hostapd_iface_switch_channel }, |
| 177 | + { "is_mld_finished", uc_hostapd_iface_is_mld_finished }, |
| 178 | }; |
| 179 | uc_value_t *data, *proto; |
| 180 | |
| 181 | -- |
| 182 | 2.18.0 |
| 183 | |