[PATCH 4/8] wifi_stats: Integration into hostapd
Iegor Sergieienkov
iegor at nova-labs.com
Thu Aug 27 07:16:21 PDT 2026
Create the wifi_stats context for each interface in
hostapd_setup_interface(), apply the configured parameters to it, and
start the collection timer. The context is freed in
hostapd_interface_deinit().
The configuration is re-applied when the interface is reloaded so that
changes to the wifi_stats_* parameters take effect without restarting
hostapd. A metric whose directive has been removed reverts to its
default rather than keeping the previously configured algorithm.
Per-station state is released in ap_free_sta() so that a station
reassociating within the aggregation span does not inherit statistics
collected during its previous association. A station that reassociates
while its struct sta_info is still present keeps its state, which matches
the lifetime of the RADIUS accounting session.
Signed-off-by: Iegor Sergieienkov <iegor at nova-labs.com>
---
src/ap/hostapd.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++
src/ap/hostapd.h | 8 ++++++
src/ap/sta_info.c | 6 +++-
3 files changed, 86 insertions(+), 1 deletion(-)
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
index 12384e792..cc2a95944 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -23,6 +23,9 @@
#include "eapol_auth/eapol_auth_sm.h"
#include "eapol_auth/eapol_auth_sm_i.h"
#include "fst/fst.h"
+#ifdef CONFIG_WIFI_STATS
+#include "wifi_stats/wifi_stats.h"
+#endif /* CONFIG_WIFI_STATS */
#include "hostapd.h"
#include "authsrv.h"
#include "sta_info.h"
@@ -60,6 +63,9 @@
static int hostapd_flush_old_stations(struct hostapd_data *hapd, u16 reason);
+#ifdef CONFIG_WIFI_STATS
+static void hostapd_reload_wifi_stats_config(struct hostapd_iface *iface);
+#endif /* CONFIG_WIFI_STATS */
#ifdef CONFIG_WEP
static int hostapd_setup_encryption(char *iface, struct hostapd_data *hapd);
static int hostapd_broadcast_wep_clear(struct hostapd_data *hapd);
@@ -300,6 +306,9 @@ int hostapd_reload_config(struct hostapd_iface *iface)
hostapd_clear_old(iface);
for (j = 0; j < iface->num_bss; j++)
hostapd_reload_bss(iface->bss[j]);
+#ifdef CONFIG_WIFI_STATS
+ hostapd_reload_wifi_stats_config(iface);
+#endif /* CONFIG_WIFI_STATS */
return 0;
}
@@ -377,6 +386,9 @@ int hostapd_reload_config(struct hostapd_iface *iface)
iface->conf = newconf;
hostapd_config_free(oldconf);
+#ifdef CONFIG_WIFI_STATS
+ hostapd_reload_wifi_stats_config(iface);
+#endif /* CONFIG_WIFI_STATS */
return 0;
}
@@ -2977,6 +2989,42 @@ int hostapd_setup_interface_complete(struct hostapd_iface *iface, int err)
}
+#ifdef CONFIG_WIFI_STATS
+static void hostapd_reload_wifi_stats_config(struct hostapd_iface *iface)
+{
+ int i;
+
+ if (!iface || !iface->wifi_stats || !iface->conf)
+ return;
+
+ wifi_stats_set_params(iface->wifi_stats,
+ iface->conf->wifi_stats_interval,
+ iface->conf->wifi_stats_wba_window);
+ wifi_stats_set_span_mode(iface->wifi_stats,
+ iface->conf->wifi_stats_span);
+ wifi_stats_set_ewma_weight(iface->wifi_stats,
+ iface->conf->wifi_stats_ewma_weight);
+
+ for (i = 0; i < WIFI_STATS_METRIC_COUNT; i++) {
+ wifi_stats_agg_type_t algorithm;
+
+ if (iface->conf->wifi_stats_metrics[i].configured)
+ algorithm = iface->conf->wifi_stats_metrics[i].algorithm;
+ else
+ algorithm = wifi_stats_default_algorithm(i);
+ wifi_stats_set_metric_config(iface->wifi_stats, i, algorithm);
+ }
+
+ wpa_printf(MSG_DEBUG,
+ "wifi_stats: Applied config (interval=%u window=%u span=%s weight=%u)",
+ iface->conf->wifi_stats_interval,
+ iface->conf->wifi_stats_wba_window,
+ wifi_stats_span_mode_to_str(iface->conf->wifi_stats_span),
+ iface->conf->wifi_stats_ewma_weight);
+}
+#endif /* CONFIG_WIFI_STATS */
+
+
/**
* hostapd_setup_interface - Setup of an interface
* @iface: Pointer to interface data.
@@ -3006,6 +3054,20 @@ int hostapd_setup_interface(struct hostapd_iface *iface)
return -1;
}
+#ifdef CONFIG_WIFI_STATS
+ if (!iface->wifi_stats)
+ iface->wifi_stats = wifi_stats_init();
+ if (!iface->wifi_stats) {
+ wpa_printf(MSG_WARNING,
+ "wifi_stats: failed to allocate context, continuing without stats");
+ } else {
+ hostapd_reload_wifi_stats_config(iface);
+ if (wifi_stats_start_timer(iface->wifi_stats, iface) != 0)
+ wpa_printf(MSG_WARNING,
+ "wifi_stats: Failed to start timer");
+ }
+#endif /* CONFIG_WIFI_STATS */
+
return 0;
}
@@ -3107,6 +3169,13 @@ void hostapd_interface_deinit(struct hostapd_iface *iface)
hostapd_stop_setup_timers(iface);
eloop_cancel_timeout(ap_ht2040_timeout, iface, NULL);
#endif /* NEED_AP_MLME */
+
+#ifdef CONFIG_WIFI_STATS
+ if (iface->wifi_stats) {
+ wifi_stats_deinit(iface->wifi_stats);
+ iface->wifi_stats = NULL;
+ }
+#endif /* CONFIG_WIFI_STATS */
}
@@ -3717,6 +3786,10 @@ int hostapd_reload_iface(struct hostapd_iface *hapd_iface)
for (j = 0; j < hapd_iface->num_bss; j++)
hostapd_reload_bss(hapd_iface->bss[j]);
+#ifdef CONFIG_WIFI_STATS
+ hostapd_reload_wifi_stats_config(hapd_iface);
+#endif /* CONFIG_WIFI_STATS */
+
return 0;
}
diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h
index 0c3ea700f..0949f34f0 100644
--- a/src/ap/hostapd.h
+++ b/src/ap/hostapd.h
@@ -40,6 +40,10 @@ struct rsn_pmksa_cache_entry;
struct mesh_conf;
#endif /* CONFIG_MESH */
+#ifdef CONFIG_WIFI_STATS
+struct wifi_stats_ctx;
+#endif /* CONFIG_WIFI_STATS */
+
#ifdef CONFIG_CTRL_IFACE_UDP
#define CTRL_IFACE_COOKIE_LEN 8
#endif /* CONFIG_CTRL_IFACE_UDP */
@@ -795,6 +799,10 @@ struct hostapd_iface {
bool data_valid;
} afc;
#endif /* CONFIG_AFC */
+
+#ifdef CONFIG_WIFI_STATS
+ struct wifi_stats_ctx *wifi_stats;
+#endif /* CONFIG_WIFI_STATS */
};
/* hostapd.c */
diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c
index 40d941cef..a1c499199 100644
--- a/src/ap/sta_info.c
+++ b/src/ap/sta_info.c
@@ -39,6 +39,9 @@
#include "sta_info.h"
#include "vlan.h"
#include "wps_hostapd.h"
+#ifdef CONFIG_WIFI_STATS
+#include "wifi_stats/wifi_stats.h"
+#endif /* CONFIG_WIFI_STATS */
#include "robust_av.h"
static void ap_sta_remove_in_other_bss(struct hostapd_data *hapd,
@@ -526,7 +529,8 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
#endif /* CONFIG_PASN */
#ifdef CONFIG_WIFI_STATS
- sta->wifi_stats = NULL;
+ if (hapd->iface && hapd->iface->wifi_stats)
+ wifi_stats_forget_sta(hapd->iface->wifi_stats, sta->addr);
#endif /* CONFIG_WIFI_STATS */
os_free(sta->ifname_wds);
--
2.43.0
More information about the Hostap
mailing list