collectd has always been able to grab interface traffic statistics from Linux. But what if we want to collect data about individual WiFi clients that connect to it? How much bandwidth is each of the clients using?
That information is already being recorded by the wireless driver; all we need to do is to query it. Turns out you can do that with the wl
utility. This is Broadcom’s proprietary tool to control and query the wireless interfaces.
To do this, first use wl
to get associated stations:
wl -i eth2 assoclist
Given a particular MAC address that is associated to the AP, query its info using sta_info
:
# wl -i eth2 sta_info d4:a3:00:aa:bb:cc
STA d4:a3:00:aa:bb:cc:
aid:2
rateset [ 6 9 12 18 24 36 48 54 ]
idle 0 seconds
in network 16 seconds
state: AUTHENTICATED ASSOCIATED AUTHORIZED
flags 0x11e03b: BRCM WME N_CAP VHT_CAP AMPDU AMSDU
HT caps 0x6f: LDPC 40MHz SGI20 SGI40
VHT caps 0x43: LDPC SGI80 SU-BFE
tx data pkts: 663916
tx data bytes: 68730715
tx ucast pkts: 155
tx ucast bytes: 42699
tx mcast/bcast pkts: 663761
tx mcast/bcast bytes: 68688016
tx failures: 0
rx data pkts: 234
rx data bytes: 73557
rx ucast pkts: 192
rx ucast bytes: 62971
rx mcast/bcast pkts: 42
rx mcast/bcast bytes: 10586
rate of last tx pkt: 866667 kbps
rate of last rx pkt: 780000 kbps
rx decrypt succeeds: 195
rx decrypt failures: 1
tx data pkts retried: 19
tx data pkts retry exhausted: 0
per antenna rssi of last rx data frame: -61 -56 -59 0
per antenna average rssi of rx data frames: -61 -56 -57 0
per antenna noise floor: -104 -98 -98 0
The “easy way” is probably to write a shell script, invoked via the Exec plugin that calls wl
multiple times (once per interface, and once for each WiFi client) and uses grep
or awk
to get the information we need. This won’t be performant, of course.
wl
itself does have quite a fair bit of overhead. It does some verification of the provided interface name. It checks for the Broadcom driver magic to ensure that the interface is a Broadcom device. It then needs to convert the MAC address from the argument string to binary, and vice-versa. Sure, that’s not really much “these days”, but we can definitely do better.
Instead, let’s short-circuit the process and write a plugin that directly collects the data, without going through wl
. This way, we avoid creating several new processes for every query.
Continue reading →