I have been using collectd on my server to monitor traffic (inbound, outbound and to/from the Internet), as well as disk stats because it’s being used as a NAS. So far it has been helpful, observing various graphs to understand patterns, and detecting problems when they happen.
I’m also recording video from a WiFi camera, so I can constantly see traffic that comes into the server. But without visibility on the router itself, I am unable to determine whether the traffic is from the 5 GHz or 2.4 GHz band, or the guest network.
By getting a collectd instance onto the router, we can get those detailed interface statistics separately.
Cross-compiling collectd
In previous articles, I have just briefly said “use the compiler with the SDK”. Here, I’ll walkthrough which compiler to use and to solve the dependencies for the toolchain.
I’m doing this on a Ubuntu 18.04 machine. I chose the Server edition because it’s easier to breeze through the installer.
RMerl (maintainer of Asuswrt-Merlin) has extracted the compiler toolchains from the various ASUSWRT source packages and placed them in a convenient repository.
Download and unpack the toolchain:
wget -O am-toolchains.zip https://github.com/RMerl/am-toolchains/archive/master.zip unzip am-toolchains.zip
Note that you may need to install unzip
on a clean machine. This should unpack to a am-toolchains-master
directory.
Installing dependencies for the compiler toolchain:
dpkg --add-architecture i386 apt update # get new lists after adding arch apt install {libmpc3,libstdc++6,libelf1}:i386
For the RT-AC68U model, the arm-brcm-linux-uclibcgnueabi
compiler in the brcm-arm-sdk
directory should be used. To get the compiler up and running, we need to fake certain old version of libraries by linking them to their newer versions 1:
cd /usr/lib/i386-linux-gnu ln -s libmpc.so.3 libmpc.so.2 ln -s libmpfr.so.6 libmpfr.so.4
Set up $PATH
to point to the directory with the toolchain:
export PATH=$PATH:~/am-toolchains-master/brcm-arm-sdk/hndtools-arm-linux-2.6.36-uclibc-4.5.3/bin
Now you can proceed to download and compile collectd:
# install dependencies apt install autoconf libtool pkg-config flex bison git clone --branch collectd-5.8.1 --depth 1 https://github.com/collectd/collectd autoreconf -i -v ./configure --host=arm-brcm-linux-uclibcgnueabi \ --prefix=/opt \ --runstatedir=/var/run \ --with-fp-layout=nothing --disable-pcie_errors make all
Note that you will need several other meta files, as I have outlined in my previous post. Those will help to automatically start the collectd process on boot. I won’t go through them again, but they are available for download below.
Gather the files to be installed into a tar.gz
archive:
make install DESTDIR=/tmp/collectd tar -C /tmp/collectd czvf collectd.tar.gz
I’m using tar.gz
because there’s no ipkg
installed on the router by default.
Installation on the Router
Copy the tar.gz
archive onto the router. You can use either a USB drive or wget
.
Unpack the archive onto the router USB drive, which is where apps are installed:
tar -C /tmp/mnt/DISK_IMG/asuswrt.arm/ xzvf collectd.tar.gz
The actual app directory and mountpoint can be inspected using the nvram
command:
# nvram get apps_mounted_path /tmp/mnt/DISK_IMG # nvram get apps_install_folder asusware.arm
Once installed, there is a ASUSWRT helper script that will do some app initialization (like copying the startup files into /opt
, symlink-ing directories, etc). We can use that to start the collectd service like so:
# app_init_run.sh collectd start collectd: script invoked with start... collectd: starting collectd... plugin_load: plugin "interface" successfully loaded. plugin_load: plugin "network" successfully loaded.
As long as the control
file says the service is enabled, it will come up automatically on the next reboot. You can check the “System Log” to verify if the service was successfully started.
Configuring collectd
I’m using a basic configuration to collect only interface statistics. The network plugin submits these collected stats to a master collectd server.
Hostname "asuswrt-1" BaseDir "/tmp" # network Interval 20 LoadPlugin interface <Plugin interface> Interface "eth1" Interface "eth2" </Plugin> LoadPlugin network <Plugin network> Server "192.168.0.1" </Plugin>
I’ve previously also collected CPU and load stats on the router, but they don’t seem to be very useful or indicative of anything.
I decided to add some simple substitution in the startup script that assists with filling in dynamic things like interface names. This means when you create a new guest network, you don’t really need to modify the collectd.conf
file. The collectd service however will need to be restarted in order for it to pick up the new interface names (which I think the system does automatically).
To get the interface names on the LAN side (wireless + wired Ethernet), you can query it from nvram like so:
nvram get lan_ifnames
To intergrate this list into the config file, a scriptlet that builds on the above example is then inserted into the appropriate location:
<Plugin interface> <? for a in `nvram get lan_ifaces`; do echo interface \"$1\"; done ?> </Plugin>
This will add Interface
config lines into the plugin section dynamically, making it easier to write a generic config file.
Stay Tuned…
The build script, together with other required files, are hosted on GitHub. The script is still a work-in-progress at the moment, but it is usable. I’ll be working towards getting it into a more polished state.
You should now be able to receive interface stats from this collectd instance running on the router, which will give you a detailed breakdown of the various wireless bands and/or guest networks.
In the next post, I’ll dive deeper into how we can collect more detailed information from the router.
- Not really recommended since the libraries might not be ABI compatible across versions, but hey, it worked. ↩