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 index 5e141e6bc..9c56e586c 100644 --- 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 @@ -1,14 +1,46 @@ local ubus = require "ubus" local bit32 = require "bit32" -local function get_wifi_interfaces() +local function get_wifi_interface_labels() local u = ubus.connect() local status = u:call("network.wireless", "status", {}) local interfaces = {} for _, dev_table in pairs(status) do for _, intf in ipairs(dev_table['interfaces']) do - table.insert(interfaces, intf['ifname']) + local cfg = intf['config'] + + -- Migrate this to ubus interface once it exposes all interesting labels + local handle = io.popen("hostapd_cli -i " .. cfg['ifname'] .." status") + local hostapd_status = handle:read("*a") + handle:close() + + local hostapd = {} + for line in hostapd_status:gmatch("[^\r\n]+") do + local name, value = string.match(line, "(.+)=(.+)") + if name == "phy" then + hostapd["vif"] = value + elseif name == "freq" then + hostapd["freq"] = value + elseif name == "channel" then + hostapd["channel"] = value + elseif name == "bssid[0]" then + hostapd["bssid"] = value + elseif name == "ssid[0]" then + hostapd["ssid"] = value + end + end + + local labels = { + vif = hostapd['vif'], + ssid = hostapd['ssid'], + bssid = hostapd['bssid'], + encryption = cfg['encryption'], -- In a mixed scenario it would be good to know if A or B was used + frequency = hostapd['freq'], + channel = hostapd['channel'], + } + + table.insert(interfaces, labels) end end @@ -25,7 +57,7 @@ local function scrape() 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") @@ -37,54 +69,50 @@ local function scrape() 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, - } - + local function evaluate_metrics(labels, vals) for k, v in pairs(vals) do if k == "flags" then if string.match(v, "[VHT]") then - metric_hostapd_station_vht(label_station, 1) + metric_hostapd_station_vht(labels, 1) end if string.match(v, "[HT]") then - metric_hostapd_station_ht(label_station, 1) + metric_hostapd_station_ht(labels, 1) end if string.match(v, "[WMM]") then - metric_hostapd_station_wmm(label_station, 1) + metric_hostapd_station_wmm(labels, 1) end if string.match(v, "[MFP]") then - metric_hostapd_station_mfp(label_station, 1) + metric_hostapd_station_mfp(labels, 1) end elseif k == "wpa" then - metric_hostapd_station_wpa(label_station, v) + metric_hostapd_station_wpa(labels, v) elseif k == "rx_packets" then - metric_hostapd_station_rx_packets(label_station, v) + metric_hostapd_station_rx_packets(labels, v) elseif k == "rx_bytes" then - metric_hostapd_station_rx_bytes(label_station, v) + metric_hostapd_station_rx_bytes(labels, v) elseif k == "tx_packets" then - metric_hostapd_station_tx_packets(label_station, v) + metric_hostapd_station_tx_packets(labels, v) elseif k == "tx_bytes" then - metric_hostapd_station_tx_bytes(label_station, v) + metric_hostapd_station_tx_bytes(labels, v) elseif k == "inactive_msec" then - metric_hostapd_station_inactive_msec(label_station, v) + metric_hostapd_station_inactive_msec(labels, v) elseif k == "signal" then - metric_hostapd_station_signal(label_station, v) + metric_hostapd_station_signal(labels, v) elseif k == "connected_time" then - metric_hostapd_station_connected_time(label_station, v) + metric_hostapd_station_connected_time(labels, v) elseif k == "sae_group" then - metric_hostapd_station_sae_group(label_station, v) + metric_hostapd_station_sae_group(labels, 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) + metric_hostapd_station_vht_capb_su_beamformee(labels, bit32.band(bit32.lshift(1, 12), caps) > 0 and 1 or 0) + metric_hostapd_station_vht_capb_mu_beamformee(labels, 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") + for _, labels in ipairs(get_wifi_interface_labels()) do + local vif = labels['vif'] + local handle = io.popen("hostapd_cli -i " .. vif .." all_sta") local all_sta = handle:read("*a") handle:close() @@ -94,7 +122,8 @@ local function scrape() 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) + labels.station = current_station + evaluate_metrics(labels, current_station_values) end current_station = line current_station_values = {} @@ -103,7 +132,8 @@ local function scrape() current_station_values[name] = value end end - evaluate_metrics(ifname, current_station, current_station_values) + labels.station = current_station + evaluate_metrics(labels, current_station_values) end end