1281681Srpaulo/* 2281681Srpaulo * BSS Load Element / Channel Utilization 3281681Srpaulo * Copyright (c) 2014, Qualcomm Atheros, Inc. 4281681Srpaulo * 5281681Srpaulo * This software may be distributed under the terms of the BSD license. 6281681Srpaulo * See README for more details. 7281681Srpaulo */ 8281681Srpaulo 9281681Srpaulo#include "utils/includes.h" 10281681Srpaulo 11281681Srpaulo#include "utils/common.h" 12281681Srpaulo#include "utils/eloop.h" 13281681Srpaulo#include "hostapd.h" 14281681Srpaulo#include "bss_load.h" 15281681Srpaulo#include "ap_drv_ops.h" 16281681Srpaulo#include "beacon.h" 17281681Srpaulo 18281681Srpaulo 19346981Scystatic int get_bss_load_update_timeout(struct hostapd_data *hapd, 20346981Scy unsigned int *sec, unsigned int *usec) 21346981Scy{ 22346981Scy unsigned int update_period = hapd->conf->bss_load_update_period; 23346981Scy unsigned int beacon_int = hapd->iconf->beacon_int; 24346981Scy unsigned int update_timeout; 25346981Scy 26346981Scy if (!update_period || !beacon_int) { 27346981Scy wpa_printf(MSG_ERROR, 28346981Scy "BSS Load: Invalid BSS load update configuration (period=%u beacon_int=%u)", 29346981Scy update_period, beacon_int); 30346981Scy return -1; 31346981Scy } 32346981Scy 33346981Scy update_timeout = update_period * beacon_int; 34346981Scy 35346981Scy *sec = ((update_timeout / 1000) * 1024) / 1000; 36346981Scy *usec = (update_timeout % 1000) * 1024; 37346981Scy 38346981Scy return 0; 39346981Scy} 40346981Scy 41346981Scy 42281681Srpaulostatic void update_channel_utilization(void *eloop_data, void *user_data) 43281681Srpaulo{ 44281681Srpaulo struct hostapd_data *hapd = eloop_data; 45281681Srpaulo unsigned int sec, usec; 46281681Srpaulo int err; 47346981Scy struct hostapd_iface *iface = hapd->iface; 48281681Srpaulo 49281681Srpaulo if (!(hapd->beacon_set_done && hapd->started)) 50281681Srpaulo return; 51281681Srpaulo 52281681Srpaulo err = hostapd_drv_get_survey(hapd, hapd->iface->freq); 53281681Srpaulo if (err) { 54281681Srpaulo wpa_printf(MSG_ERROR, "BSS Load: Failed to get survey data"); 55281681Srpaulo return; 56281681Srpaulo } 57281681Srpaulo 58281681Srpaulo ieee802_11_set_beacon(hapd); 59281681Srpaulo 60346981Scy if (get_bss_load_update_timeout(hapd, &sec, &usec) < 0) 61346981Scy return; 62346981Scy 63346981Scy if (hapd->conf->chan_util_avg_period) { 64346981Scy iface->chan_util_samples_sum += iface->channel_utilization; 65346981Scy iface->chan_util_num_sample_periods += 66346981Scy hapd->conf->bss_load_update_period; 67346981Scy if (iface->chan_util_num_sample_periods >= 68346981Scy hapd->conf->chan_util_avg_period) { 69346981Scy iface->chan_util_average = 70346981Scy iface->chan_util_samples_sum / 71346981Scy (iface->chan_util_num_sample_periods / 72346981Scy hapd->conf->bss_load_update_period); 73346981Scy iface->chan_util_samples_sum = 0; 74346981Scy iface->chan_util_num_sample_periods = 0; 75346981Scy } 76346981Scy } 77346981Scy 78281681Srpaulo eloop_register_timeout(sec, usec, update_channel_utilization, hapd, 79281681Srpaulo NULL); 80281681Srpaulo} 81281681Srpaulo 82281681Srpaulo 83281681Srpauloint bss_load_update_init(struct hostapd_data *hapd) 84281681Srpaulo{ 85281681Srpaulo unsigned int sec, usec; 86281681Srpaulo 87346981Scy if (get_bss_load_update_timeout(hapd, &sec, &usec) < 0) 88281681Srpaulo return -1; 89281681Srpaulo 90281681Srpaulo eloop_register_timeout(sec, usec, update_channel_utilization, hapd, 91281681Srpaulo NULL); 92281681Srpaulo return 0; 93281681Srpaulo} 94281681Srpaulo 95281681Srpaulo 96281681Srpaulovoid bss_load_update_deinit(struct hostapd_data *hapd) 97281681Srpaulo{ 98281681Srpaulo eloop_cancel_timeout(update_channel_utilization, hapd, NULL); 99281681Srpaulo} 100