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
19static 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
42static 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
83int 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
96void bss_load_update_deinit(struct hostapd_data *hapd)
97{
98	eloop_cancel_timeout(update_channel_utilization, hapd, NULL);
99}
100