1 /* 2 * BSS Load Element / Channel Utilization 3 * Copyright (c) 2014, Qualcomm Atheros, Inc. 4 * 5 * This software may be distributed under the terms of the BSD license. 6 * See README for more details. 7 */ 8 9 #include "utils/includes.h" 10 11 #include "utils/common.h" 12 #include "utils/eloop.h" 13 #include "hostapd.h" 14 #include "bss_load.h" 15 #include "ap_drv_ops.h" 16 #include "beacon.h" 17 18 19 static int get_bss_load_update_timeout(struct hostapd_data *hapd, 20 unsigned int *sec, unsigned int *usec) 21 { 22 unsigned int update_period = hapd->conf->bss_load_update_period; 23 unsigned int beacon_int = hapd->iconf->beacon_int; 24 unsigned int update_timeout; 25 26 if (!update_period || !beacon_int) { 27 wpa_printf(MSG_ERROR, 28 "BSS Load: Invalid BSS load update configuration (period=%u beacon_int=%u)", 29 update_period, beacon_int); 30 return -1; 31 } 32 33 update_timeout = update_period * beacon_int; 34 35 *sec = ((update_timeout / 1000) * 1024) / 1000; 36 *usec = (update_timeout % 1000) * 1024; 37 38 return 0; 39 } 40 41 42 static void update_channel_utilization(void *eloop_data, void *user_data) 43 { 44 struct hostapd_data *hapd = eloop_data; 45 unsigned int sec, usec; 46 int err; 47 struct hostapd_iface *iface = hapd->iface; 48 49 if (!(hapd->beacon_set_done && hapd->started)) 50 return; 51 52 err = hostapd_drv_get_survey(hapd, hapd->iface->freq); 53 if (err) { 54 wpa_printf(MSG_ERROR, "BSS Load: Failed to get survey data"); 55 return; 56 } 57 58 ieee802_11_set_beacon(hapd); 59 60 if (get_bss_load_update_timeout(hapd, &sec, &usec) < 0) 61 return; 62 63 if (hapd->conf->chan_util_avg_period) { 64 iface->chan_util_samples_sum += iface->channel_utilization; 65 iface->chan_util_num_sample_periods += 66 hapd->conf->bss_load_update_period; 67 if (iface->chan_util_num_sample_periods >= 68 hapd->conf->chan_util_avg_period) { 69 iface->chan_util_average = 70 iface->chan_util_samples_sum / 71 (iface->chan_util_num_sample_periods / 72 hapd->conf->bss_load_update_period); 73 iface->chan_util_samples_sum = 0; 74 iface->chan_util_num_sample_periods = 0; 75 } 76 } 77 78 eloop_register_timeout(sec, usec, update_channel_utilization, hapd, 79 NULL); 80 } 81 82 83 int bss_load_update_init(struct hostapd_data *hapd) 84 { 85 unsigned int sec, usec; 86 87 if (get_bss_load_update_timeout(hapd, &sec, &usec) < 0) 88 return -1; 89 90 eloop_register_timeout(sec, usec, update_channel_utilization, hapd, 91 NULL); 92 return 0; 93 } 94 95 96 void bss_load_update_deinit(struct hostapd_data *hapd) 97 { 98 eloop_cancel_timeout(update_channel_utilization, hapd, NULL); 99 } 100