]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
AP: Add support for BSS load element (STA Count, Channel Utilization)
authorKyeyoon Park <kyeyoonp@qca.qualcomm.com>
Wed, 15 Oct 2014 23:36:04 +0000 (16:36 -0700)
committerJouni Malinen <j@w1.fi>
Tue, 21 Oct 2014 20:25:48 +0000 (23:25 +0300)
The new "bss_load_update_period" parameter can be used to configure
hostapd to advertise its BSS Load element in Beacon and Probe Response
frames. This parameter is in the units of BUs (Beacon Units).

When enabled, the STA Count and the Channel Utilization value will be
updated periodically in the BSS Load element. The AAC is set to 0 sinze
explicit admission control is not supported. Channel Utilization is
calculated based on the channel survey information from the driver and
as such, requires a driver that supports providing that information for
the current operating channel.

Signed-off-by: Kyeyoon Park <kyeyoonp@qca.qualcomm.com>
13 files changed:
hostapd/Android.mk
hostapd/Makefile
hostapd/config_file.c
hostapd/hostapd.conf
src/ap/ap_config.h
src/ap/beacon.c
src/ap/bss_load.c [new file with mode: 0644]
src/ap/bss_load.h [new file with mode: 0644]
src/ap/drv_callbacks.c
src/ap/hostapd.c
src/ap/hostapd.h
wpa_supplicant/Android.mk
wpa_supplicant/Makefile

index edaf6fc8e615776235d1d666c588bb4bdd29b575..84a8778197bbe9fa38daea8a6133f174a264eb19 100644 (file)
@@ -95,6 +95,7 @@ OBJS += src/ap/preauth_auth.c
 OBJS += src/ap/pmksa_cache_auth.c
 OBJS += src/ap/ieee802_11_shared.c
 OBJS += src/ap/beacon.c
+OBJS += src/ap/bss_load.c
 OBJS_d =
 OBJS_p =
 LIBS =
index ac6373e6c22cc641b1fe9a04c6420e7469a960ea..dc5eacdb7d425ef00aa7d5761db7560e989bdeab 100644 (file)
@@ -59,6 +59,7 @@ OBJS += ../src/ap/preauth_auth.o
 OBJS += ../src/ap/pmksa_cache_auth.o
 OBJS += ../src/ap/ieee802_11_shared.o
 OBJS += ../src/ap/beacon.o
+OBJS += ../src/ap/bss_load.o
 
 OBJS_c = hostapd_cli.o ../src/common/wpa_ctrl.o ../src/utils/os_$(CONFIG_OS).o
 
index d4ba7cc0cf882c73df8e03b441c7e2f03d0ab49f..ddebf1f468029e43d9db6865b71d91d24fb487ac 100644 (file)
@@ -2489,6 +2489,15 @@ static int hostapd_config_fill(struct hostapd_config *conf,
                                   line, bss->dtim_period);
                        return 1;
                }
+       } else if (os_strcmp(buf, "bss_load_update_period") == 0) {
+               bss->bss_load_update_period = atoi(pos);
+               if (bss->bss_load_update_period < 0 ||
+                   bss->bss_load_update_period > 100) {
+                       wpa_printf(MSG_ERROR,
+                                  "Line %d: invalid bss_load_update_period %d",
+                                  line, bss->bss_load_update_period);
+                       return 1;
+               }
        } else if (os_strcmp(buf, "rts_threshold") == 0) {
                conf->rts_threshold = atoi(pos);
                if (conf->rts_threshold < 0 || conf->rts_threshold > 2347) {
index d4e5bf0af26a8fab44861af7f56dada7ff4324d7..2e6f841bfb74141af968633b337f9a7cd5da938d 100644 (file)
@@ -435,6 +435,11 @@ wmm_ac_vo_acm=0
 # associated stations in the BSS. By default, this bridging is allowed.
 #ap_isolate=1
 
+# BSS Load update period (in BUs)
+# This field is used to enable and configure adding a BSS Load element into
+# Beacon and Probe Response frames.
+#bss_load_update_period=50
+
 # 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
index e37a796596ce1234655b1ea4684e63661f40d5d6..b693664e43dc6ba06583e66be2597de135c92b24 100644 (file)
@@ -196,6 +196,7 @@ struct hostapd_bss_config {
        int max_num_sta; /* maximum number of STAs in station table */
 
        int dtim_period;
+       int bss_load_update_period;
 
        int ieee802_1x; /* use IEEE 802.1X */
        int eapol_version;
index 4cae0d993a409ef15d70d780d6f092ed4950e6b4..22aef9f60cae6ee1ad2185bc6abecccb3b6ec6ac 100644 (file)
 
 static u8 * hostapd_eid_bss_load(struct hostapd_data *hapd, u8 *eid, size_t len)
 {
+       if (len < 2 + 5)
+               return eid;
+
 #ifdef CONFIG_TESTING_OPTIONS
        if (hapd->conf->bss_load_test_set) {
-               if (2 + 5 > len)
-                       return eid;
                *eid++ = WLAN_EID_BSS_LOAD;
                *eid++ = 5;
                os_memcpy(eid, hapd->conf->bss_load_test, 5);
                eid += 5;
+               return eid;
        }
 #endif /* CONFIG_TESTING_OPTIONS */
+       if (hapd->conf->bss_load_update_period) {
+               *eid++ = WLAN_EID_BSS_LOAD;
+               *eid++ = 5;
+               WPA_PUT_LE16(eid, hapd->num_sta);
+               eid += 2;
+               *eid++ = hapd->iface->channel_utilization;
+               WPA_PUT_LE16(eid, 0); /* no available admission capabity */
+               eid += 2;
+       }
        return eid;
 }
 
diff --git a/src/ap/bss_load.c b/src/ap/bss_load.c
new file mode 100644 (file)
index 0000000..fb63942
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * BSS Load Element / Channel Utilization
+ * Copyright (c) 2014, Qualcomm Atheros, Inc.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "utils/includes.h"
+
+#include "utils/common.h"
+#include "utils/eloop.h"
+#include "hostapd.h"
+#include "bss_load.h"
+#include "ap_drv_ops.h"
+#include "beacon.h"
+
+
+static void update_channel_utilization(void *eloop_data, void *user_data)
+{
+       struct hostapd_data *hapd = eloop_data;
+       unsigned int sec, usec;
+       int err;
+
+       if (!(hapd->beacon_set_done && hapd->started))
+               return;
+
+       err = hostapd_drv_get_survey(hapd, hapd->iface->freq);
+       if (err) {
+               wpa_printf(MSG_ERROR, "BSS Load: Failed to get survey data");
+               return;
+       }
+
+       ieee802_11_set_beacon(hapd);
+
+       sec = ((hapd->bss_load_update_timeout / 1000) * 1024) / 1000;
+       usec = (hapd->bss_load_update_timeout % 1000) * 1024;
+       eloop_register_timeout(sec, usec, update_channel_utilization, hapd,
+                              NULL);
+}
+
+
+int bss_load_update_init(struct hostapd_data *hapd)
+{
+       struct hostapd_bss_config *conf = hapd->conf;
+       struct hostapd_config *iconf = hapd->iconf;
+       unsigned int sec, usec;
+
+       if (!conf->bss_load_update_period || !iconf->beacon_int)
+               return -1;
+
+       hapd->bss_load_update_timeout = conf->bss_load_update_period *
+                                       iconf->beacon_int;
+       sec = ((hapd->bss_load_update_timeout / 1000) * 1024) / 1000;
+       usec = (hapd->bss_load_update_timeout % 1000) * 1024;
+       eloop_register_timeout(sec, usec, update_channel_utilization, hapd,
+                              NULL);
+       return 0;
+}
+
+
+void bss_load_update_deinit(struct hostapd_data *hapd)
+{
+       eloop_cancel_timeout(update_channel_utilization, hapd, NULL);
+}
diff --git a/src/ap/bss_load.h b/src/ap/bss_load.h
new file mode 100644 (file)
index 0000000..ac3c793
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * BSS load update
+ * Copyright (c) 2014, Qualcomm Atheros, Inc.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef BSS_LOAD_UPDATE_H
+#define BSS_LOAD_UPDATE_H
+
+
+int bss_load_update_init(struct hostapd_data *hapd);
+void bss_load_update_deinit(struct hostapd_data *hapd);
+
+
+#endif /* BSS_LOAD_UPDATE_H */
index 3bde7205db08c6583136248651a9baf0f5713cdd..9beb32245461053c9c09b67294a0107616c4c292 100644 (file)
@@ -858,6 +858,42 @@ static void hostapd_update_nf(struct hostapd_iface *iface,
 }
 
 
+static void hostapd_single_channel_get_survey(struct hostapd_iface *iface,
+                                             struct survey_results *survey_res)
+{
+       struct hostapd_channel_data *chan;
+       struct freq_survey *survey;
+       u64 divisor, dividend;
+
+       survey = dl_list_first(&survey_res->survey_list, struct freq_survey,
+                              list);
+       if (!survey || !survey->freq)
+               return;
+
+       chan = hostapd_get_mode_channel(iface, survey->freq);
+       if (!chan || chan->flag & HOSTAPD_CHAN_DISABLED)
+               return;
+
+       wpa_printf(MSG_DEBUG, "Single Channel Survey: (freq=%d channel_time=%ld channel_time_busy=%ld)",
+                  survey->freq,
+                  (unsigned long int) survey->channel_time,
+                  (unsigned long int) survey->channel_time_busy);
+
+       if (survey->channel_time > iface->last_channel_time &&
+           survey->channel_time > survey->channel_time_busy) {
+               dividend = survey->channel_time_busy -
+                       iface->last_channel_time_busy;
+               divisor = survey->channel_time - iface->last_channel_time;
+
+               iface->channel_utilization = dividend * 255 / divisor;
+               wpa_printf(MSG_DEBUG, "Channel Utilization: %d",
+                          iface->channel_utilization);
+       }
+       iface->last_channel_time = survey->channel_time;
+       iface->last_channel_time_busy = survey->channel_time_busy;
+}
+
+
 static void hostapd_event_get_survey(struct hostapd_data *hapd,
                                     struct survey_results *survey_results)
 {
@@ -870,6 +906,11 @@ static void hostapd_event_get_survey(struct hostapd_data *hapd,
                return;
        }
 
+       if (survey_results->freq_filter) {
+               hostapd_single_channel_get_survey(iface, survey_results);
+               return;
+       }
+
        dl_list_for_each_safe(survey, tmp, &survey_results->survey_list,
                              struct freq_survey, list) {
                chan = hostapd_get_mode_channel(iface, survey->freq);
index 764722f96f6f8b999fb6756b6e6a469c676045f6..be7dfd8cc881086e6fbb03003c0c366f1cc54e9f 100644 (file)
@@ -35,6 +35,7 @@
 #include "gas_serv.h"
 #include "dfs.h"
 #include "ieee802_11.h"
+#include "bss_load.h"
 
 
 static int hostapd_flush_old_stations(struct hostapd_data *hapd, u16 reason);
@@ -310,6 +311,8 @@ static void hostapd_free_hapd_data(struct hostapd_data *hapd)
        gas_serv_deinit(hapd);
 #endif /* CONFIG_INTERWORKING */
 
+       bss_load_update_deinit(hapd);
+
 #ifdef CONFIG_SQLITE
        bin_clear_free(hapd->tmp_eap_user.identity,
                       hapd->tmp_eap_user.identity_len);
@@ -875,6 +878,11 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
        }
 #endif /* CONFIG_INTERWORKING */
 
+       if (conf->bss_load_update_period && bss_load_update_init(hapd)) {
+               wpa_printf(MSG_ERROR, "BSS Load initialization failed");
+               return -1;
+       }
+
        if (!hostapd_drv_none(hapd) && vlan_init(hapd)) {
                wpa_printf(MSG_ERROR, "VLAN initialization failed.");
                return -1;
index ca01a688e25a50106870a83a9e375bf6c124ee91..50ebe0eff9eb87a649b317416b01c5991c31854d 100644 (file)
@@ -218,6 +218,9 @@ struct hostapd_data {
        unsigned int cs_c_off_proberesp;
        int csa_in_progress;
 
+       /* BSS Load */
+       unsigned int bss_load_update_timeout;
+
 #ifdef CONFIG_P2P
        struct p2p_data *p2p;
        struct p2p_group *p2p_group;
@@ -354,6 +357,11 @@ struct hostapd_iface {
        /* lowest observed noise floor in dBm */
        s8 lowest_nf;
 
+       /* channel utilization calculation */
+       u64 last_channel_time;
+       u64 last_channel_time_busy;
+       u8 channel_utilization;
+
        unsigned int dfs_cac_ms;
        struct os_reltime dfs_cac_start;
 
index 8b7df6c77a7b1d7b83ea8846b612487911460378..7d1bb9eae1591b5fd17a8920c4331a94ba58c7f2 100644 (file)
@@ -767,6 +767,7 @@ OBJS += src/ap/ieee802_11_shared.c
 OBJS += src/ap/drv_callbacks.c
 OBJS += src/ap/ap_drv_ops.c
 OBJS += src/ap/beacon.c
+OBJS += src/ap/bss_load.c
 OBJS += src/ap/eap_user_db.c
 ifdef CONFIG_IEEE80211N
 OBJS += src/ap/ieee802_11_ht.c
index 7eee73a9d0518a5f99b95b07702751f22ad61f94..6556ec48a9b9175359a2db19115b39a024d104aa 100644 (file)
@@ -782,6 +782,7 @@ OBJS += ../src/ap/ieee802_11_shared.o
 OBJS += ../src/ap/drv_callbacks.o
 OBJS += ../src/ap/ap_drv_ops.o
 OBJS += ../src/ap/beacon.o
+OBJS += ../src/ap/bss_load.o
 OBJS += ../src/ap/eap_user_db.o
 ifdef CONFIG_IEEE80211N
 OBJS += ../src/ap/ieee802_11_ht.o