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 
get_bss_load_update_timeout(struct hostapd_data * hapd,unsigned int * sec,unsigned int * usec)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 
update_channel_utilization(void * eloop_data,void * user_data)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_per_bss_only(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 
bss_load_update_init(struct hostapd_data * hapd)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 
bss_load_update_deinit(struct hostapd_data * hapd)96 void bss_load_update_deinit(struct hostapd_data *hapd)
97 {
98           eloop_cancel_timeout(update_channel_utilization, hapd, NULL);
99 }
100