developer | 2980895 | 2023-11-18 07:50:06 +0800 | [diff] [blame] | 1 | From 920a20927f1537ae2a6ce9c7123ef189e83cd0a0 Mon Sep 17 00:00:00 2001 |
developer | de22665 | 2023-11-11 12:19:01 +0800 | [diff] [blame] | 2 | From: Evelyn Tsai <evelyn.tsai@mediatek.com> |
| 3 | Date: Sat, 11 Nov 2023 11:42:59 +0800 |
| 4 | Subject: [PATCH] hostapd: mtk: ACS: Fix 2.4GHz HT40 case and channel switch |
| 5 | fail |
| 6 | |
| 7 | Issue#1. Add 2.4G HT40- support |
| 8 | 1. Add 2.4G HT40- support |
| 9 | 2. Fix issue: selected best channel is out of channels |
| 10 | |
| 11 | Issue#2. Fix chan_switch to usable DFS channel fail due to ACS |
| 12 | |
| 13 | Step and issue: |
| 14 | 1. Enable ACS in hostapd config; |
| 15 | 2. Bootup and then use hostapd_cli cmd switch channel to a DFS channel; |
| 16 | 3. Will do ACS again, and no work on channel specified in step 2. |
| 17 | |
| 18 | Root cause: |
| 19 | When need do DFS-CAC, hostapd will do intf disable, then set the new |
| 20 | channel into running config settings, and finally enable intf; |
| 21 | In the test case, new DFS channel is set to runnint config settings, but |
| 22 | another param "acs" is still 1 (enable), caused the ACS running when |
| 23 | intf enabled. |
developer | de22665 | 2023-11-11 12:19:01 +0800 | [diff] [blame] | 24 | --- |
developer | 2980895 | 2023-11-18 07:50:06 +0800 | [diff] [blame] | 25 | src/ap/acs.c | 142 ++++++++++++++++++++++++++--------------------- |
developer | de22665 | 2023-11-11 12:19:01 +0800 | [diff] [blame] | 26 | src/ap/hostapd.c | 3 + |
developer | 2980895 | 2023-11-18 07:50:06 +0800 | [diff] [blame] | 27 | 2 files changed, 83 insertions(+), 62 deletions(-) |
developer | de22665 | 2023-11-11 12:19:01 +0800 | [diff] [blame] | 28 | |
| 29 | diff --git a/src/ap/acs.c b/src/ap/acs.c |
developer | 2980895 | 2023-11-18 07:50:06 +0800 | [diff] [blame] | 30 | index 130e135..65573b9 100644 |
developer | de22665 | 2023-11-11 12:19:01 +0800 | [diff] [blame] | 31 | --- a/src/ap/acs.c |
| 32 | +++ b/src/ap/acs.c |
developer | 2980895 | 2023-11-18 07:50:06 +0800 | [diff] [blame] | 33 | @@ -712,10 +712,19 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface, |
developer | de22665 | 2023-11-11 12:19:01 +0800 | [diff] [blame] | 34 | struct hostapd_channel_data **ideal_chan, |
| 35 | long double *ideal_factor) |
| 36 | { |
| 37 | - struct hostapd_channel_data *chan, *adj_chan = NULL, *best; |
| 38 | + struct hostapd_channel_data *chan, *adj_chan = NULL, *tmp_chan = NULL, *best; |
| 39 | long double factor; |
| 40 | int i, j; |
| 41 | unsigned int k; |
| 42 | + int ht40_plus = 1, sec_ch_factor = 1; |
| 43 | + |
| 44 | + if (is_24ghz_mode(mode->mode)) { |
| 45 | + ht40_plus = (iface->conf->secondary_channel == -1) ? 0 : 1; |
| 46 | + sec_ch_factor = (iface->conf->secondary_channel == -1) ? -1 : 1; |
| 47 | + } |
| 48 | + |
| 49 | + wpa_printf(MSG_INFO, "%s:%d, bw(%u), n_chans(%d), num_channels(%d), sec_ch(%d)", |
| 50 | + __func__, __LINE__, bw, n_chans, mode->num_channels, iface->conf->secondary_channel); |
| 51 | |
| 52 | for (i = 0; i < mode->num_channels; i++) { |
| 53 | double total_weight; |
developer | 2980895 | 2023-11-18 07:50:06 +0800 | [diff] [blame] | 54 | @@ -723,6 +732,9 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface, |
| 55 | bool update_best = true; |
developer | de22665 | 2023-11-11 12:19:01 +0800 | [diff] [blame] | 56 | |
| 57 | best = chan = &mode->channels[i]; |
| 58 | + wpa_printf(MSG_INFO, |
| 59 | + "ACS: Channel[%d] %d: interference_factor %Lg", |
| 60 | + i, chan->chan, chan->interference_factor); |
| 61 | |
| 62 | /* Since in the current ACS implementation the first channel is |
| 63 | * always a primary channel, skip channels not available as |
developer | 2980895 | 2023-11-18 07:50:06 +0800 | [diff] [blame] | 64 | @@ -747,7 +759,7 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface, |
developer | de22665 | 2023-11-11 12:19:01 +0800 | [diff] [blame] | 65 | if (chan->flag & HOSTAPD_CHAN_INDOOR_ONLY && iface->conf->country[2] == 0x4f) |
| 66 | continue; |
| 67 | |
| 68 | - if (!chan_bw_allowed(chan, bw, 1, 1)) { |
| 69 | + if (!chan_bw_allowed(chan, bw, ht40_plus, 1)) { |
| 70 | wpa_printf(MSG_DEBUG, |
| 71 | "ACS: Channel %d: BW %u is not supported", |
| 72 | chan->chan, bw); |
developer | 2980895 | 2023-11-18 07:50:06 +0800 | [diff] [blame] | 73 | @@ -789,60 +801,73 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface, |
developer | de22665 | 2023-11-11 12:19:01 +0800 | [diff] [blame] | 74 | } |
| 75 | |
| 76 | factor = 0; |
| 77 | - if (acs_usable_chan(chan)) |
| 78 | - factor = chan->interference_factor; |
| 79 | - total_weight = 1; |
developer | 2980895 | 2023-11-18 07:50:06 +0800 | [diff] [blame] | 80 | - |
developer | de22665 | 2023-11-11 12:19:01 +0800 | [diff] [blame] | 81 | - for (j = 1; j < n_chans; j++) { |
| 82 | - adj_chan = acs_find_chan(iface, chan->freq + (j * 20)); |
| 83 | - if (!adj_chan) |
| 84 | - break; |
developer | 2980895 | 2023-11-18 07:50:06 +0800 | [diff] [blame] | 85 | + total_weight = 0; |
| 86 | |
developer | de22665 | 2023-11-11 12:19:01 +0800 | [diff] [blame] | 87 | - if (!chan_bw_allowed(adj_chan, bw, 1, 0)) { |
| 88 | - wpa_printf(MSG_DEBUG, |
| 89 | - "ACS: PRI Channel %d: secondary channel %d BW %u is not supported", |
| 90 | - chan->chan, adj_chan->chan, bw); |
| 91 | - break; |
| 92 | - } |
| 93 | - |
| 94 | - if (acs_usable_chan(adj_chan)) { |
| 95 | - factor += adj_chan->interference_factor; |
| 96 | + if (!is_24ghz_mode(mode->mode)) { |
| 97 | + /* If the AP is in the 5 GHz or 6 GHz band, lets prefer a less |
| 98 | + * crowded primary channel if one was found in the segment */ |
| 99 | + if (acs_usable_chan(chan)) { |
| 100 | + factor += chan->interference_factor; |
| 101 | total_weight += 1; |
| 102 | - } else { |
| 103 | - update_best = false; |
| 104 | } |
| 105 | |
| 106 | - /* find the best channel in this segment */ |
| 107 | - if (update_best && |
| 108 | - adj_chan->interference_factor < |
| 109 | - best->interference_factor) |
| 110 | - best = adj_chan; |
| 111 | - } |
| 112 | + for (j = 1; j < n_chans; j++) { |
| 113 | + adj_chan = acs_find_chan(iface, chan->freq + j * 20); |
| 114 | + if (!adj_chan) |
| 115 | + break; |
| 116 | |
| 117 | - if (j != n_chans) { |
| 118 | - wpa_printf(MSG_DEBUG, "ACS: Channel %d: not enough bandwidth", |
| 119 | - chan->chan); |
| 120 | - continue; |
| 121 | - } |
developer | 2980895 | 2023-11-18 07:50:06 +0800 | [diff] [blame] | 122 | + if (!is_in_chanlist(iface, adj_chan) || !is_in_freqlist(iface, adj_chan)) |
developer | de22665 | 2023-11-11 12:19:01 +0800 | [diff] [blame] | 123 | + break; |
developer | de22665 | 2023-11-11 12:19:01 +0800 | [diff] [blame] | 124 | |
| 125 | - /* If the AP is in the 5 GHz or 6 GHz band, lets prefer a less |
| 126 | - * crowded primary channel if one was found in the segment */ |
| 127 | - if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211A && |
| 128 | - chan != best) { |
| 129 | - wpa_printf(MSG_DEBUG, |
| 130 | - "ACS: promoting channel %d over %d (less interference %Lg/%Lg)", |
| 131 | - best->chan, chan->chan, |
| 132 | - chan->interference_factor, |
| 133 | - best->interference_factor); |
| 134 | - chan = best; |
| 135 | - } |
developer | 2980895 | 2023-11-18 07:50:06 +0800 | [diff] [blame] | 136 | + if (!chan_bw_allowed(adj_chan, bw, 1, 0)) { |
| 137 | + wpa_printf(MSG_DEBUG, |
| 138 | + "ACS: PRI Channel %d: secondary channel %d BW %u is not supported", |
| 139 | + chan->chan, adj_chan->chan, bw); |
| 140 | + break; |
| 141 | + } |
| 142 | |
| 143 | - /* 2.4 GHz has overlapping 20 MHz channels. Include adjacent |
| 144 | - * channel interference factor. */ |
| 145 | - if (is_24ghz_mode(mode->mode)) { |
developer | de22665 | 2023-11-11 12:19:01 +0800 | [diff] [blame] | 146 | + update_best = true; |
| 147 | + if (acs_usable_chan(adj_chan)) { |
| 148 | + factor += adj_chan->interference_factor; |
| 149 | + total_weight += 1; |
developer | de22665 | 2023-11-11 12:19:01 +0800 | [diff] [blame] | 150 | + } else { |
| 151 | + update_best = false; |
| 152 | + } |
| 153 | + |
| 154 | + /* find the best channel in this segment */ |
developer | 2980895 | 2023-11-18 07:50:06 +0800 | [diff] [blame] | 155 | + if (update_best && |
| 156 | + adj_chan->interference_factor < best->interference_factor) |
developer | de22665 | 2023-11-11 12:19:01 +0800 | [diff] [blame] | 157 | + best = adj_chan; |
developer | de22665 | 2023-11-11 12:19:01 +0800 | [diff] [blame] | 158 | + } |
developer | 2980895 | 2023-11-18 07:50:06 +0800 | [diff] [blame] | 159 | + |
| 160 | + if (j != n_chans) { |
developer | de22665 | 2023-11-11 12:19:01 +0800 | [diff] [blame] | 161 | + wpa_printf(MSG_DEBUG, "ACS: Channel %d: not enough bandwidth", |
| 162 | + chan->chan); |
| 163 | + continue; |
| 164 | + } |
| 165 | + |
| 166 | + if (chan != best) { |
| 167 | + wpa_printf(MSG_INFO, |
| 168 | + "ACS: promoting channel %d over %d (less interference %Lg/%Lg)", |
| 169 | + best->chan, chan->chan, |
| 170 | + chan->interference_factor, |
| 171 | + best->interference_factor); |
| 172 | + chan = best; |
| 173 | + } |
| 174 | + } else { |
| 175 | for (j = 0; j < n_chans; j++) { |
| 176 | + /* Will set primary_channel / secondary_channel(40M case) weight to 1 */ |
| 177 | + tmp_chan = acs_find_chan(iface, chan->freq + |
developer | 2980895 | 2023-11-18 07:50:06 +0800 | [diff] [blame] | 178 | + (j * sec_ch_factor * 20)); |
developer | de22665 | 2023-11-11 12:19:01 +0800 | [diff] [blame] | 179 | + if (tmp_chan && acs_usable_chan(tmp_chan)) { |
| 180 | + factor += tmp_chan->interference_factor; |
| 181 | + total_weight += 1; |
| 182 | + } |
| 183 | + |
| 184 | + /* 2.4 GHz has overlapping 20 MHz channels. Include adjacent channel |
| 185 | + interference factor, separately for primary/secondary channel. */ |
| 186 | adj_chan = acs_find_chan(iface, chan->freq + |
| 187 | - (j * 20) - 5); |
developer | 2980895 | 2023-11-18 07:50:06 +0800 | [diff] [blame] | 188 | + (j * sec_ch_factor * 20) - 5); |
developer | de22665 | 2023-11-11 12:19:01 +0800 | [diff] [blame] | 189 | if (adj_chan && acs_usable_chan(adj_chan)) { |
| 190 | factor += ACS_ADJ_WEIGHT * |
| 191 | adj_chan->interference_factor; |
developer | 2980895 | 2023-11-18 07:50:06 +0800 | [diff] [blame] | 192 | @@ -850,7 +875,7 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface, |
developer | de22665 | 2023-11-11 12:19:01 +0800 | [diff] [blame] | 193 | } |
| 194 | |
| 195 | adj_chan = acs_find_chan(iface, chan->freq + |
| 196 | - (j * 20) - 10); |
developer | 2980895 | 2023-11-18 07:50:06 +0800 | [diff] [blame] | 197 | + (j * sec_ch_factor * 20) - 10); |
developer | de22665 | 2023-11-11 12:19:01 +0800 | [diff] [blame] | 198 | if (adj_chan && acs_usable_chan(adj_chan)) { |
| 199 | factor += ACS_NEXT_ADJ_WEIGHT * |
| 200 | adj_chan->interference_factor; |
developer | 2980895 | 2023-11-18 07:50:06 +0800 | [diff] [blame] | 201 | @@ -858,7 +883,7 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface, |
developer | de22665 | 2023-11-11 12:19:01 +0800 | [diff] [blame] | 202 | } |
| 203 | |
| 204 | adj_chan = acs_find_chan(iface, chan->freq + |
| 205 | - (j * 20) + 5); |
developer | 2980895 | 2023-11-18 07:50:06 +0800 | [diff] [blame] | 206 | + (j * sec_ch_factor * 20) + 5); |
developer | de22665 | 2023-11-11 12:19:01 +0800 | [diff] [blame] | 207 | if (adj_chan && acs_usable_chan(adj_chan)) { |
| 208 | factor += ACS_ADJ_WEIGHT * |
| 209 | adj_chan->interference_factor; |
developer | 2980895 | 2023-11-18 07:50:06 +0800 | [diff] [blame] | 210 | @@ -866,7 +891,7 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface, |
developer | de22665 | 2023-11-11 12:19:01 +0800 | [diff] [blame] | 211 | } |
| 212 | |
| 213 | adj_chan = acs_find_chan(iface, chan->freq + |
| 214 | - (j * 20) + 10); |
developer | 2980895 | 2023-11-18 07:50:06 +0800 | [diff] [blame] | 215 | + (j * sec_ch_factor * 20) + 10); |
developer | de22665 | 2023-11-11 12:19:01 +0800 | [diff] [blame] | 216 | if (adj_chan && acs_usable_chan(adj_chan)) { |
| 217 | factor += ACS_NEXT_ADJ_WEIGHT * |
| 218 | adj_chan->interference_factor; |
developer | 2980895 | 2023-11-18 07:50:06 +0800 | [diff] [blame] | 219 | @@ -875,7 +900,8 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface, |
developer | de22665 | 2023-11-11 12:19:01 +0800 | [diff] [blame] | 220 | } |
| 221 | } |
| 222 | |
| 223 | - factor /= total_weight; |
| 224 | + if (total_weight) |
| 225 | + factor /= total_weight; |
| 226 | |
| 227 | bias = NULL; |
| 228 | if (iface->conf->acs_chan_bias) { |
developer | 2980895 | 2023-11-18 07:50:06 +0800 | [diff] [blame] | 229 | @@ -894,11 +920,11 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface, |
developer | de22665 | 2023-11-11 12:19:01 +0800 | [diff] [blame] | 230 | |
| 231 | if (bias) { |
| 232 | factor *= bias->bias; |
| 233 | - wpa_printf(MSG_DEBUG, |
| 234 | + wpa_printf(MSG_INFO, |
| 235 | "ACS: * channel %d: total interference = %Lg (%f bias)", |
| 236 | chan->chan, factor, bias->bias); |
| 237 | } else { |
| 238 | - wpa_printf(MSG_DEBUG, |
| 239 | + wpa_printf(MSG_INFO, |
| 240 | "ACS: * channel %d: total interference = %Lg", |
| 241 | chan->chan, factor); |
| 242 | } |
developer | 2980895 | 2023-11-18 07:50:06 +0800 | [diff] [blame] | 243 | @@ -939,14 +965,6 @@ acs_find_ideal_chan(struct hostapd_iface *iface) |
developer | de22665 | 2023-11-11 12:19:01 +0800 | [diff] [blame] | 244 | goto bw_selected; |
| 245 | } |
| 246 | |
| 247 | - /* TODO: HT40- support */ |
| 248 | - |
| 249 | - if (iface->conf->ieee80211n && |
| 250 | - iface->conf->secondary_channel == -1) { |
| 251 | - wpa_printf(MSG_ERROR, "ACS: HT40- is not supported yet. Please try HT40+"); |
| 252 | - return NULL; |
| 253 | - } |
| 254 | - |
| 255 | if (iface->conf->ieee80211n && |
| 256 | iface->conf->secondary_channel) |
| 257 | n_chans = 2; |
developer | 2980895 | 2023-11-18 07:50:06 +0800 | [diff] [blame] | 258 | @@ -981,7 +999,7 @@ bw_selected: |
developer | de22665 | 2023-11-11 12:19:01 +0800 | [diff] [blame] | 259 | } |
| 260 | |
| 261 | if (ideal_chan) { |
| 262 | - wpa_printf(MSG_DEBUG, "ACS: Ideal channel is %d (%d MHz) with total interference factor of %Lg", |
| 263 | + wpa_printf(MSG_INFO, "ACS: Ideal channel is %d (%d MHz) with total interference factor of %Lg", |
| 264 | ideal_chan->chan, ideal_chan->freq, ideal_factor); |
| 265 | return ideal_chan; |
| 266 | } |
developer | de22665 | 2023-11-11 12:19:01 +0800 | [diff] [blame] | 267 | diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c |
| 268 | index f2eb638..250c168 100644 |
| 269 | --- a/src/ap/hostapd.c |
| 270 | +++ b/src/ap/hostapd.c |
| 271 | @@ -3895,6 +3895,9 @@ hostapd_switch_channel_fallback(struct hostapd_iface *iface, |
| 272 | |
| 273 | iface->freq = freq_params->freq; |
| 274 | iface->conf->channel = freq_params->channel; |
| 275 | + if (iface->conf->channel != 0) /* If channel not zero, will disable acs. */ |
| 276 | + iface->conf->acs = 0; |
| 277 | + |
| 278 | iface->conf->secondary_channel = freq_params->sec_channel_offset; |
| 279 | hostapd_set_oper_centr_freq_seg0_idx(iface->conf, seg0_idx); |
| 280 | hostapd_set_oper_centr_freq_seg1_idx(iface->conf, seg1_idx); |
| 281 | -- |
| 282 | 2.18.0 |
| 283 | |