EHT: Calculate puncturing bitmap for ACS

Generate puncturing bitmap after the ideal channel selection using
the threshold.

Signed-off-by: Aloka Dixit <quic_alokad@quicinc.com>
This commit is contained in:
Aloka Dixit 2023-03-13 21:59:24 -07:00 committed by Jouni Malinen
parent f3206fbe94
commit af0f60e7dd
2 changed files with 90 additions and 1 deletions

View file

@ -326,6 +326,7 @@ static void acs_cleanup_mode(struct hostapd_hw_modes *mode)
dl_list_init(&chan->survey_list); dl_list_init(&chan->survey_list);
chan->flag |= HOSTAPD_CHAN_SURVEY_LIST_INITIALIZED; chan->flag |= HOSTAPD_CHAN_SURVEY_LIST_INITIALIZED;
chan->min_nf = 0; chan->min_nf = 0;
chan->punct_bitmap = 0;
} }
} }
@ -711,6 +712,55 @@ static int is_common_24ghz_chan(int chan)
#define ACS_24GHZ_PREFER_1_6_11 0.8 #define ACS_24GHZ_PREFER_1_6_11 0.8
#endif /* ACS_24GHZ_PREFER_1_6_11 */ #endif /* ACS_24GHZ_PREFER_1_6_11 */
#ifdef CONFIG_IEEE80211BE
static void acs_update_puncturing_bitmap(struct hostapd_iface *iface,
struct hostapd_hw_modes *mode, u32 bw,
int n_chans,
struct hostapd_channel_data *chan,
long double factor,
int index_primary)
{
struct hostapd_config *conf = iface->conf;
struct hostapd_channel_data *adj_chan = NULL;
int i;
long double threshold;
/*
* If threshold is 0 or user configured puncturing pattern is
* available then don't add additional puncturing.
*/
if (!conf->punct_acs_threshold || conf->punct_bitmap)
return;
if (is_24ghz_mode(mode->mode) || bw < 80)
return;
threshold = factor * conf->punct_acs_threshold / 100;
for (i = 0; i < n_chans; i++) {
int adj_freq;
if (i == index_primary)
continue; /* Cannot puncture primary channel */
if (i > index_primary)
adj_freq = chan->freq + (i - index_primary) * 20;
else
adj_freq = chan->freq - (index_primary - i) * 20;
adj_chan = acs_find_chan(iface, adj_freq);
if (!adj_chan) {
chan->punct_bitmap = 0;
return;
}
if (adj_chan->interference_factor > threshold)
chan->punct_bitmap |= BIT(i);
}
}
#endif /* CONFIG_IEEE80211BE */
static void static void
acs_find_ideal_chan_mode(struct hostapd_iface *iface, acs_find_ideal_chan_mode(struct hostapd_iface *iface,
struct hostapd_hw_modes *mode, struct hostapd_hw_modes *mode,
@ -734,7 +784,13 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
/* Since in the current ACS implementation the first channel is /* Since in the current ACS implementation the first channel is
* always a primary channel, skip channels not available as * always a primary channel, skip channels not available as
* primary until more sophisticated channel selection is * primary until more sophisticated channel selection is
* implemented. */ * implemented.
*
* If this implementation is changed to allow any channel in
* the bandwidth to be the primary one, the last parameter to
* acs_update_puncturing_bitmap() should be changed to the index
* of the primary channel
*/
if (!chan_pri_allowed(chan)) if (!chan_pri_allowed(chan))
continue; continue;
@ -913,8 +969,20 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
if (acs_usable_chan(chan) && if (acs_usable_chan(chan) &&
(!*ideal_chan || factor < *ideal_factor)) { (!*ideal_chan || factor < *ideal_factor)) {
/* Reset puncturing bitmap for the previous ideal
* channel */
if (*ideal_chan)
(*ideal_chan)->punct_bitmap = 0;
*ideal_factor = factor; *ideal_factor = factor;
*ideal_chan = chan; *ideal_chan = chan;
#ifdef CONFIG_IEEE80211BE
if (iface->conf->ieee80211be)
acs_update_puncturing_bitmap(iface, mode, bw,
n_chans, chan,
factor, 0);
#endif /* CONFIG_IEEE80211BE */
} }
/* This channel would at least be usable */ /* This channel would at least be usable */
@ -991,9 +1059,22 @@ bw_selected:
if (ideal_chan) { if (ideal_chan) {
wpa_printf(MSG_DEBUG, "ACS: Ideal channel is %d (%d MHz) with total interference factor of %Lg", wpa_printf(MSG_DEBUG, "ACS: Ideal channel is %d (%d MHz) with total interference factor of %Lg",
ideal_chan->chan, ideal_chan->freq, ideal_factor); ideal_chan->chan, ideal_chan->freq, ideal_factor);
#ifdef CONFIG_IEEE80211BE
if (iface->conf->punct_acs_threshold)
wpa_printf(MSG_DEBUG, "ACS: RU puncturing bitmap 0x%x",
ideal_chan->punct_bitmap);
#endif /* CONFIG_IEEE80211BE */
return ideal_chan; return ideal_chan;
} }
#ifdef CONFIG_IEEE80211BE
if (iface->conf->punct_acs_threshold)
wpa_printf(MSG_DEBUG, "ACS: RU puncturing bitmap 0x%x",
ideal_chan->punct_bitmap);
#endif /* CONFIG_IEEE80211BE */
return rand_chan; return rand_chan;
} }
@ -1106,6 +1187,9 @@ static void acs_study(struct hostapd_iface *iface)
iface->conf->channel = ideal_chan->chan; iface->conf->channel = ideal_chan->chan;
iface->freq = ideal_chan->freq; iface->freq = ideal_chan->freq;
#ifdef CONFIG_IEEE80211BE
iface->conf->punct_bitmap = ideal_chan->punct_bitmap;
#endif /* CONFIG_IEEE80211BE */
if (iface->conf->ieee80211ac || iface->conf->ieee80211ax) { if (iface->conf->ieee80211ac || iface->conf->ieee80211ax) {
acs_adjust_secondary(iface); acs_adjust_secondary(iface);

View file

@ -170,6 +170,11 @@ struct hostapd_channel_data {
* wmm_rules - WMM regulatory rules * wmm_rules - WMM regulatory rules
*/ */
struct hostapd_wmm_rule wmm_rules[WMM_AC_NUM]; struct hostapd_wmm_rule wmm_rules[WMM_AC_NUM];
/**
* punct_bitmap - RU puncturing bitmap
*/
u16 punct_bitmap;
}; };
#define HE_MAC_CAPAB_0 0 #define HE_MAC_CAPAB_0 0