diff --git a/hostapd/config_file.c b/hostapd/config_file.c index f1e84b7c9..289180428 100644 --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -2863,6 +2863,16 @@ static int hostapd_config_fill(struct hostapd_config *conf, return 1; } bss->bss_load_update_period = val; + } else if (os_strcmp(buf, "chan_util_avg_period") == 0) { + int val = atoi(pos); + + if (val < 0) { + wpa_printf(MSG_ERROR, + "Line %d: invalid chan_util_avg_period", + line); + return 1; + } + bss->chan_util_avg_period = val; } else if (os_strcmp(buf, "rts_threshold") == 0) { conf->rts_threshold = atoi(pos); if (conf->rts_threshold < -1 || conf->rts_threshold > 65535) { diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf index 140c8d6ff..0d49fd744 100644 --- a/hostapd/hostapd.conf +++ b/hostapd/hostapd.conf @@ -511,6 +511,12 @@ wmm_ac_vo_acm=0 # Beacon and Probe Response frames. #bss_load_update_period=50 +# Channel utilization averaging period (in BUs) +# This field is used to enable and configure channel utilization average +# calculation with bss_load_update_period. This should be in multiples of +# bss_load_update_period for more accurate calculation. +#chan_util_avg_period=600 + # Fixed BSS Load value for testing purposes # This field can be used to configure hostapd to add a fixed BSS Load element # into Beacon and Probe Response frames for testing purposes. The format is diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h index fa99d3750..dc0686e69 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -249,6 +249,7 @@ struct hostapd_bss_config { int dtim_period; unsigned int bss_load_update_period; + unsigned int chan_util_avg_period; int ieee802_1x; /* use IEEE 802.1X */ int eapol_version; diff --git a/src/ap/bss_load.c b/src/ap/bss_load.c index ef2d36be3..725d3cd34 100644 --- a/src/ap/bss_load.c +++ b/src/ap/bss_load.c @@ -44,6 +44,7 @@ static void update_channel_utilization(void *eloop_data, void *user_data) struct hostapd_data *hapd = eloop_data; unsigned int sec, usec; int err; + struct hostapd_iface *iface = hapd->iface; if (!(hapd->beacon_set_done && hapd->started)) return; @@ -59,6 +60,21 @@ static void update_channel_utilization(void *eloop_data, void *user_data) if (get_bss_load_update_timeout(hapd, &sec, &usec) < 0) return; + if (hapd->conf->chan_util_avg_period) { + iface->chan_util_samples_sum += iface->channel_utilization; + iface->chan_util_num_sample_periods += + hapd->conf->bss_load_update_period; + if (iface->chan_util_num_sample_periods >= + hapd->conf->chan_util_avg_period) { + iface->chan_util_average = + iface->chan_util_samples_sum / + (iface->chan_util_num_sample_periods / + hapd->conf->bss_load_update_period); + iface->chan_util_samples_sum = 0; + iface->chan_util_num_sample_periods = 0; + } + } + eloop_register_timeout(sec, usec, update_channel_utilization, hapd, NULL); } diff --git a/src/ap/ctrl_iface_ap.c b/src/ap/ctrl_iface_ap.c index 74d3a2577..883b005b2 100644 --- a/src/ap/ctrl_iface_ap.c +++ b/src/ap/ctrl_iface_ap.c @@ -795,6 +795,15 @@ int hostapd_ctrl_iface_status(struct hostapd_data *hapd, char *buf, len += ret; } + if (hapd->conf->chan_util_avg_period) { + ret = os_snprintf(buf + len, buflen - len, + "chan_util_avg=%u\n", + iface->chan_util_average); + if (os_snprintf_error(buflen - len, ret)) + return len; + len += ret; + } + return len; } diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h index 2c095dcfa..0e35ee80a 100644 --- a/src/ap/hostapd.h +++ b/src/ap/hostapd.h @@ -497,6 +497,10 @@ struct hostapd_iface { u64 last_channel_time_busy; u8 channel_utilization; + unsigned int chan_util_samples_sum; + unsigned int chan_util_num_sample_periods; + unsigned int chan_util_average; + /* eCSA IE will be added only if operating class is specified */ u8 cs_oper_class;