From af8f8f80469fe595171d9dd4895a7dc0fbe0e29b Mon Sep 17 00:00:00 2001 From: David Bauer Date: Wed, 4 Dec 2019 00:40:08 +0100 Subject: [PATCH] prometheus-node-exporter-lua: add hostapd exporter This exporter exposes information of the connected stations acquired from hostapd. These contain additional information compared to the existing station exporter, however they require a full build of hostapd / wpad. Signed-off-by: David Bauer --- utils/prometheus-node-exporter-lua/Makefile | 16 ++- .../hostapd_stations.lua | 110 ++++++++++++++++++ 2 files changed, 124 insertions(+), 2 deletions(-) create mode 100644 utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/hostapd_stations.lua diff --git a/utils/prometheus-node-exporter-lua/Makefile b/utils/prometheus-node-exporter-lua/Makefile index 06b28ee9de..3d676c385e 100644 --- a/utils/prometheus-node-exporter-lua/Makefile +++ b/utils/prometheus-node-exporter-lua/Makefile @@ -4,8 +4,8 @@ include $(TOPDIR)/rules.mk PKG_NAME:=prometheus-node-exporter-lua -PKG_VERSION:=2019.11.17 -PKG_RELEASE:=2 +PKG_VERSION:=2020.02.03 +PKG_RELEASE:=1 PKG_MAINTAINER:=Etienne CHAMPETIER PKG_LICENSE:=Apache-2.0 @@ -58,6 +58,12 @@ define Package/prometheus-node-exporter-lua-wifi_stations DEPENDS:=prometheus-node-exporter-lua +libiwinfo-lua +libubus-lua endef +define Package/prometheus-node-exporter-lua-hostapd_stations + $(call Package/prometheus-node-exporter-lua/Default) + TITLE+= (hostapd_stations collector) - Requires a full hostapd / wpad build + DEPENDS:=prometheus-node-exporter-lua +hostapd-utils +lua-bit32 +libubus-lua +endef + define Package/prometheus-node-exporter-lua-bmx6 $(call Package/prometheus-node-exporter-lua/Default) TITLE+= (bmx6 links collector) @@ -128,6 +134,11 @@ define Package/prometheus-node-exporter-lua-wifi_stations/install $(INSTALL_BIN) ./files/usr/lib/lua/prometheus-collectors/wifi_stations.lua $(1)/usr/lib/lua/prometheus-collectors/ endef +define Package/prometheus-node-exporter-lua-hostapd_stations/install + $(INSTALL_DIR) $(1)/usr/lib/lua/prometheus-collectors + $(INSTALL_BIN) ./files/usr/lib/lua/prometheus-collectors/hostapd_stations.lua $(1)/usr/lib/lua/prometheus-collectors/ +endef + define Package/prometheus-node-exporter-lua-bmx6/install $(INSTALL_DIR) $(1)/usr/lib/lua/prometheus-collectors $(INSTALL_BIN) ./files/usr/lib/lua/prometheus-collectors/bmx6.lua $(1)/usr/lib/lua/prometheus-collectors/ @@ -158,6 +169,7 @@ $(eval $(call BuildPackage,prometheus-node-exporter-lua-nat_traffic)) $(eval $(call BuildPackage,prometheus-node-exporter-lua-netstat)) $(eval $(call BuildPackage,prometheus-node-exporter-lua-wifi)) $(eval $(call BuildPackage,prometheus-node-exporter-lua-wifi_stations)) +$(eval $(call BuildPackage,prometheus-node-exporter-lua-hostapd_stations)) $(eval $(call BuildPackage,prometheus-node-exporter-lua-bmx6)) $(eval $(call BuildPackage,prometheus-node-exporter-lua-bmx7)) $(eval $(call BuildPackage,prometheus-node-exporter-lua-textfile)) diff --git a/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/hostapd_stations.lua b/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/hostapd_stations.lua new file mode 100644 index 0000000000..47ae9a5c59 --- /dev/null +++ b/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/hostapd_stations.lua @@ -0,0 +1,110 @@ +local ubus = require "ubus" +local bit32 = require "bit32" + +local function get_wifi_interfaces() + local u = ubus.connect() + local status = u:call("network.wireless", "status", {}) + local interfaces = {} + + for dev, dev_table in pairs(status) do + for _, intf in ipairs(dev_table['interfaces']) do + table.insert(interfaces, intf['config']['ifname']) + end + end + + return interfaces +end + +local function scrape() + local metric_hostapd_station_vht = metric("hostapd_station_vht", "gauge") + local metric_hostapd_station_ht = metric("hostapd_station_ht", "gauge") + local metric_hostapd_station_wmm = metric("hostapd_station_wmm", "gauge") + local metric_hostapd_station_mfp = metric("hostapd_station_mfp", "gauge") + + local metric_hostapd_station_rx_packets = metric("hostapd_station_rx_packets", "counter") + local metric_hostapd_station_rx_bytes = metric("hostapd_station_rx_bytes", "counter") + local metric_hostapd_station_tx_packets = metric("hostapd_station_tx_packets", "counter") + local metric_hostapd_station_tx_bytes = metric("hostapd_station_tx_bytes", "counter") + + local metric_hostapd_station_inactive_msec = metric("hostapd_station_inactive_msec", "counter") + + local metric_hostapd_station_signal = metric("hostapd_station_signal", "gauge") + local metric_hostapd_station_connected_time = metric("hostapd_station_connected_time", "counter") + + local metric_hostapd_station_wpa = metric("hostapd_station_wpa", "gauge") + local metric_hostapd_station_sae_group = metric("hostapd_station_sae_group", "gauge") + + local metric_hostapd_station_vht_capb_su_beamformee = metric("hostapd_station_vht_capb_su_beamformee", "gauge") + local metric_hostapd_station_vht_capb_mu_beamformee = metric("hostapd_station_vht_capb_mu_beamformee", "gauge") + + local function evaluate_metrics(ifname, station, vals) + local label_station = { + ifname = ifname, + station = station, + } + + for k, v in pairs(vals) do + if k == "flags" then + if string.match(v, "[VHT]") then + metric_hostapd_station_vht(label_station, 1) + end + if string.match(v, "[HT]") then + metric_hostapd_station_ht(label_station, 1) + end + if string.match(v, "[WMM]") then + metric_hostapd_station_wmm(label_station, 1) + end + if string.match(v, "[MFP]") then + metric_hostapd_station_mfp(label_station, 1) + end + elseif k == "wpa" then + metric_hostapd_station_wpa(label_station, v) + elseif k == "rx_packets" then + metric_hostapd_station_rx_packets(label_station, v) + elseif k == "rx_bytes" then + metric_hostapd_station_rx_bytes(label_station, v) + elseif k == "tx_packets" then + metric_hostapd_station_tx_packets(label_station, v) + elseif k == "tx_bytes" then + metric_hostapd_station_tx_bytes(label_station, v) + elseif k == "inactive_msec" then + metric_hostapd_station_inactive_msec(label_station, v) + elseif k == "signal" then + metric_hostapd_station_signal(label_station, v) + elseif k == "connected_time" then + metric_hostapd_station_connected_time(label_station, v) + elseif k == "sae_group" then + metric_hostapd_station_sae_group(label_station, v) + elseif k == "vht_caps_info" then + local caps = tonumber(string.gsub(v, "0x", ""), 16) + metric_hostapd_station_vht_capb_su_beamformee(label_station, bit32.band(bit32.lshift(1, 12), caps) > 0 and 1 or 0) + metric_hostapd_station_vht_capb_mu_beamformee(label_station, bit32.band(bit32.lshift(1, 20), caps) > 0 and 1 or 0) + end + end + end + + for _, ifname in ipairs(get_wifi_interfaces()) do + local handle = io.popen("hostapd_cli -i " .. ifname .." all_sta") + local all_sta = handle:read("*a") + handle:close() + + local current_station = nil + local current_station_values = {} + + for line in all_sta:gmatch("[^\r\n]+") do + if string.match(line, "^%x[0123456789aAbBcCdDeE]:%x%x:%x%x:%x%x:%x%x:%x%x$") then + if current_station ~= nil then + evaluate_metrics(ifname, current_station, current_station_values) + end + current_station = line + current_station_values = {} + else + local name, value = string.match(line, "(.+)=(.+)") + current_station_values[name] = value + end + end + evaluate_metrics(ifname, current_station, current_station_values) + end +end + +return { scrape = scrape } -- 2.30.2