User Tools

Site Tools



2016-11-17: The package maintainer is currently working on an update of the package that will be available in trunk in a few weeks: it will have the ability to store in a sqlite database and graph this data with php: this will be in a new package: bandwidthd-sqlite. Also bandwidthd (all packages) will report SMTP traffic instead of the P2P traffic.

Bandwidthd is composed of 3 packages (4 soon):

  1. bandwidthd: this package cannot save in a postgresql database. This package is currently available in trunk, 15.05.1 and OpenWrt version older than Chaos Calmer (ex: 14.07): for 15.05, it has to be compiled. This allows the router to generate bandwidth data that is accessible with a browser at Use this package if you have no intention of storing the data on a postgresql or sqlite database.
  2. bandwidthd-pgsql: this package can do everything the bandwidthd package can do, but in addition it can save the data to a postgresql database that can reside on the router or on another server. This data can be analyzed by a series of PHP scripts and visualized with a browser. Note that the router, the posgresql database and the graphing of the data by PHP can be on three different systems, one for each task (i.e.: collecting the data, storing the postgresql data and generating the graphs with PHP). Note that postgresql does not have to be installed on the router if the postgresql data is not stored on the router. bandwidthd-pgsql requires the package libpq to be installed: this package is already installed if postgresql is installed. NOTE: install only one of the package: bandwidthd or bandwidthd-pgsql.
  3. bandwidthd-php: This package contains the PHP files that are installed in /www/phphtdocs on the router. It is only required if the OpenWrt router serves as the web server to generate the graphs from the data on the postgresql database by pointing the browser to
  4. An additional package will be added: bandwidthd-sqlite. This package, in addition to do what the plain bandwidthd package can do, will also store the data in a sqlite database on the router and be able to graph, using PHP. In a way, it will be a combination of bandwidthd-pgsql and bandwidthd-php together, but using sqlite instead of postgresql.

The availability of each package varies according to which version of OpenWrt you have:


  • In Backfire (10.03 or 10.03.1) as a package.
  • In Attitude Adjustment (12.09) as a package.
  • In Barrier Breaker (14.07) in "oldpackages" as a package.
  • In original Chaos Calmer (15.05) it is not available as a precompiled package: you have to compile it yourself and install it. See to have details on how to compile a package.
  • In the minor fix release of Chaos Calmer (15.05.1) it is available as a package.



  • Available in trunk as a package and uses php7 (php5 is not available anymore in trunk). The PHP files found in the trunk package work fine with Chaos Calmer 15.05 or 15.05.1 with php5 (tested) and should work for php7 (not tested and php7 is not available in Chaos Calmer)


  • Will be available soon in trunk and will use php7 and sqlite.


For the bandwidthd package:

opkg install bandwidthd uhttpd
/etc/init.d/uhttpd enable
/etc/init.d/uhttpd start
/etc/init.d/bandwidthd enable
/etc/init.d/bandwidthd start

For the bandwidthd-pgsql package (note: do not install uhttpd if you do not plan for the router to perform the graphs):

opkg install bandwidthd-pgsql uhttpd
/etc/init.d/uhttpd enable
/etc/init.d/uhttpd start
/etc/init.d/bandwidthd enable
/etc/init.d/bandwidthd start

With all dependencies it uses around 500 kB of storage space. If you have not changes the IP address of your router (, then the web page with the bandwidthd data will be available at If you have changed the IP address of your router, then edit the /etc/config/bandwidthd file to correct the address.

Limitations and CPU usage

Bandwidthd uses a lot of cpu power to process and analyse packages, on average TP-Link TL-WR841ND router with 400 Mhz CPU it maxes out CPU with 100% usage around 3 Mpbs speeds. So if you have faster connection it throttles it down to around 3 Mbps because CPU can't handle more packages.

Note: As of build r31249 this is not necessarily true. While bandwidthd still maxes out at 100% cpu and >4 load average even while idle, the router will happily exceed 70mbps download speeds even with QoS on, which by itself uses >80% cpu at those speeds. In other words, even while bandwidthd is using 100% cpu, the above router will still easily exceed most people's connection speeds without the CPU becoming a limitation.

If the data is stored in a postgresql database with bandwidthd-pgsql and the graphs are made by another system than the OpenWrt router, the CPU requirements is much lighter.


Edit /etc/config/bandwidthd

The bandwidthd-pgsql package has the same behavior when installed as the bandwidthd package: to record in a postgresql database a couple of configuration that are disabled needs to be enabled. See below, in the section Storing bandwidthd stats in a postgresql database, on how to activate them.


By default, bandwidthd hosts its statistics at /bandwidthd. For example, if the OpenWRT router's IP address is, bandwidthd's stats would be available at

bandwidthd-pgsql can perform the same as bandwidthd, and this is the default behavior. If the settings for bandwidthd-pgsql are to store in a postgresql database and not perform the graphs, then PHP has to be used to generate the graphs (see below).

Storing bandwidthd stats in external permanent storage

NOTE: This information is old and was written before the current maintainer of the bandwidthd package updated this HOWTO. The information is probably outdated. If you are able to perform this, please let the author know about it and provide the information so this HOWTO can be updated. The default bandwidthd installation loses your previous statistics on each reboot. To keep statistics between reboots it is needed to modify "/etc/config/bandwidthd" and "/etc/init.d/bandwidthd"

The only thing to understand is that bandwidthd binary, when launched, looks for the "httpd" folder and "bandwidthd.conf" file in the same folder where the binary has been lauched. Default /etc/init.d/bandwidthd init script creates two symlinks:

/httpd >> /www/bandwidthd
/bandwidthd.conf >> /etc/bandwidthd.conf 

then move to / folder and lauches there the bandwidthd binary.

These modifications change the init script behaviour to create httpd folder and bandwidthd.conf file in external storage.

Suppose we have a usb stick mounted in /mnt/usb and will store the bandwidthd stats in /mnt/usb/bandwidthd. Just modify the start() function in /etc/init.d/bandwidthd

start() {
        local subnet conffile
        [ -d /mnt/usb/bandwidthd/htdocs ] || mkdir -p /mnt/usb/bandwidthd/htdocs && cp /www/legend.gif /www/logo.gif /mnt/usb/bandwidthd/htdocs
        [ -e /www/bandwidthd ] || ln -s /mnt/usb/bandwidthd/htdocs /www/bandwidthd
        rm -f /mnt/usb/bandwidthd/bandwidthd.conf
        touch /mnt/usb/bandwidthd/bandwidthd.conf
        [ -e /etc/bandwidthd.conf ] || ln -s /mnt/usb/bandwidthd/bandwidthd.conf /etc/bandwidthd.conf
        config_load bandwidthd
        for cfg in $cfgs; do
                config_get subnets $cfg subnets
                        for subnet in $subnets; do
                                conffile="${conffile}subnet ${subnet}\n"
                export_string dev $cfg
                export_number skip_intervals $cfg
                export_number graph_cutoff $cfg
                export_bool promiscuous $cfg
                export_bool output_cdf $cfg
                export_bool recover_cdf $cfg
                export_string filter $cfg
                export_bool graph $cfg
                export_number meta_refresh $cfg
                [ -n "$conffile" ] && echo -e "$conffile" >>/mnt/usb/bandwidthd/bandwidthd.conf
                unset conffile
        cd /mnt/usb/bandwidthd

Next modify /etc/config/bandwidthd file to save statistics to disk. You need to change "option output_cdf true" and "option recover_cdf true"

config bandwidthd
	option dev		br-lan
	option subnets		""
	option skip_intervals	0
	option graph_cutoff	1024
	option promiscuous	true
	option output_cdf	true
	option recover_cdf	true
	option filter		ip
	option graph		true
	option meta_refresh	150

After modifying both of the files, restart the service. Afterwards, you will get a file and directory structure on your external mount like this:

root@openwrt:~# ls -la /mnt/usb/bandwidthd/
drwxr-xr-x    3 root     root         1024 Aug 25 12:21 .
drwxr-xr-x    6 root     root         1024 Aug 25 00:39 ..
-rw-r--r--    1 root     root          158 Aug 25 00:40 bandwidthd.conf
drwxr-xr-x    2 root     root         2048 Aug 25 00:40 htdocs
-rw-r--r--    1 root     root        50034 Aug 25 12:21 log.1.0.cdf
-rw-r--r--    1 root     root        22204 Aug 25 12:21 log.2.0.cdf
-rw-r--r--    1 root     root         6698 Aug 25 12:10 log.3.0.cdf
-rw-r--r--    1 root     root          529 Aug 25 00:39 log.4.0.cdf

Storing bandwidthd stats in a postgresql database

Bandwidthd now has support for external databases: it is provided by the bandwidthd-pgsql package: the bandwidthd package does not support this. This system consists of 3 major parts, and each part can be on a different server:

  1. The bandwidthd binary which acts as a sensor, recording traffic information and storing it in a database across the network or on the OpenWrt router. In this mode Bandwidthd uses very little ram and CPU. In addition, multiple sensors can record to the same database.
  2. The database system. Currently Bandwidthd only supports Postgresql. Please note that the postgres-server package on OpenWrt is pretty big (the server and a blank database takes more than 15 MB) and unless you have at lot of memory in your router, you will not be able to install it!
  3. The webserver and php application. The package bandwidthd-php provides the required file if these have to run on the OpenWrt router. In the "/www/phphtdocs" directory is a php application that reports on and graphs the contents of the database. This has been designed to be easy to customize. Everything is passed around on the urls, just tinker with it a little and you'll see how to generate custom graphs pretty easy.

Using Bandwidthd with a database has many advantages, such as much lower overhead, because graphs are only graphed on demand. And much more flexibility, SQL makes building new reports easy, and php+sql greatly improves the interactivity of the reports.

It is strongly recommended to use the router only to collect the data and store it to another server running postgres. That same server can also be running the web server and use PHP to generate the graphs, but generating the graphs can take a lot of CPU time for a router and the various packages (postgresql, php) uses a lot of memory space that most router do not have.


As a prerequisite for these instructions, you must have Postgresql server installed and working for the database, as well as a web server that supports php for the web server that will generate the graphs. Consult to have more information on installing postgresql on OpenWrt. For other OSes (Linux, NetBSD, Unix, etc.) consult the help on the respective OS.

Database Setup: Note that the database can reside on a remote computer and does not have to be on the OpenWrt router. If not using the router for the database, the required files for the setup can be found at

  1. Create a database for bandwidthd. You will need to create a user that can access the database remotely if you want remote sensors. In OpenWrt, log as the user postgres (su - postgres) and issue the command "createdb bandwidthd", then go back to be the root user with "exit".
  2. Bandwidthd's schema is in "schema.postgresql" that can be found in /usr/share/postgresql (provided by the bandwidthd-pgsql package). "psql mydb username < schema.postgresql" should load it and create the 2 tables and 4 indexes.

In addition, you should schedule to run every so often. I recommend running it weekly. This script outputs sql statements that aggregate the older data points in your database in order to reduce the amount of data that needs to be slogged through in order to generate yearly, monthly, and weekly graphs.

Example to be run as the postgres user: | psql bandwidthd postgres

Will connect to the bandwidthd database on local host as the user postgres and summarize the data.

Bandwidthd Setup: Here is the /etc/config/bandwidthd file in the bandwidthd-pgsql package:

config bandwidthd
        option dev      br-lan
        option subnets          ""
        option skip_intervals   0
        option graph_cutoff     1024
        option promiscuous      true
        option output_cdf       false
        option recover_cdf      false
        option filter           ip
        option graph            true
        option meta_refresh     150
        option disabled_pgsql_connect_string    "user = postgres dbname = bandwidthd host ="
        option disabled_sensor_id       "openwrt.mydomain.domain"

To activate the storage to a postgresql database, modify the following lines:

option graph false
   If you leave it at on, you will still get the graphs at
option pgsql_connect_string    "user = theuser dbname = bandwidthd host ="
   Remove the disabled_ portion to activate it
   Change the user variable to the proper username
   Change the dbname variable to the database name (by default it is bandwidthd)
   Change the host variable to the IP address (or the domain name) of the postghresql server
 option sensor_id "openwrt.mydomain.domain"
   Remove the disabled_ portion to activate it
   Change the name to the name that you want for your sensor: the name you give is not really critical.

Simply start bandwidthd (/etc/init.d/bandwidthd start), and after a few minutes data should start appearing in your database. If not, check syslog for error messages.

Web Server Setup: Note that the web server can be on a remote web server and does not have to reside on the OpenWrt router. Consult for installation of PHP on OpenWrt. For other OSes (Linux, NetBSD, Unix, etc.) consult the help on the respective OS. You will also have to configure the web server to work with PHP. Running this on OpenWrt takes about 2 MB of storage space for the various packages.

  1. Copy the contents of phphtdocs into your web tree somewhere: these files are available at or in the bandwidthd-php package: the package will install them automatically and puts then in /www/phphtdocs.
  2. Edit the file bandwidthd-php in /etc/config to set your db connect string ($db_connect_string = "host= user=postgres dbname=bandwidthd"). The variables host, user and dbname have to be edited in order to connect to the database.
  3. On OpenWrt, the following packages will be installed automatically: libpcre; libxml2; php7; php7-cgi; php7-mod-pgsql and php7-mod-gd. On another system, the corresponding packages should be installed. Note that it also works with php5 which to be used on Chaos Calmer as php7 is not available.
  4. With php5, a zoneinfo package should be installed (ex: zoneinfo-northamerica or zoneinfo-europe). This is required to set the date.timezone value in php.ini.
  5. If you are not using the bandwidthd-php package on OpenWrt, the file /etc/php.ini should be edited to have the following: short_open_tag = On: the reason is that the php files taken from have the php short tag (<? ?>) instead of the normal tag (<?php ?>). If you do not do it, then you will get a bunch of garbage on the screen. If you installed the bandwidthd-php package on your router, then this is not necessary to set the short_open_tag = at On as the tags in the php files have been corrected to have <?php ?>.
  6. In the /etc/php.ini file with php5, the date.timezone = should be edited to a valid value (ex:date.timezone = "America/Montreal"). Without the date.timezone set to something valid, the graphs will not be drawn.
  7. If you are using uhttpd, the following line should be added to /etc/config/uhttpd: list interpreter ".php=/usr/bin/php-cgi"

You should now be able to access the web application and see you graphs. All graphing is done by graph.php, all parameters are passed to it in it's url. You can create custom urls to pull custom graphs from your own index pages, or use the canned reporting system.

Monitoring the Internet bandwidth of each host in a network

One advantage of bandwidthd is the ability to provide the bandwidth usage of each host in a network. If you want to monitor the Internet usage of each host in your network, you can set bandwidthd in an OpenWrt system between the Internet router and the network.

Here is the way that I do it in my home:

  • I have a router (non-OpenWrt, although an OpenWrt system can be used) connected to the Internet on the WAN side that creates a private network (192.168.XXX.XXX/24) on the LAN side.
  • I have a TP-WDR3600, with OpenWrt (Chaos Calmer 15.05) setup to monitor the bandwidth using bandwidthd (from the package bandwidthd-pgsql) that stores the data on a postgresql database on a server on the private network: this server also has the PHP files to generate the graphs with the web server application (Apache. Any web server supporting PHP can be used): the PHP files are the one from bandwidthd-php.
  • The non-OpenWrt router is connected to port 3 of the TP-WDR3600.
  • On the TP-WDR3600, port 4 is connected to port 2: yes there is a small Cat5 cable between port 4 and 2 of the TP-WDR3600.
  • Port 1 of the TP-WDR3600 is connected to a switch to which the whole private network is connected: the TP-WDR3600 is between the non-OpenWrt router (on port 3) and the private network (on port 1).
  • Traffic from the Internet arrives from the non-OpenWrt router to port 3 of the TP-WDR3600 and goes out from port 4 to go back in on port 2 and then go out on port 1 to the switch on the private network.
  • The same way, traffic to the internet leaves the switch on the private network to enter the TP-WDR3600 on port 1, goes out on port 2, enter again on port 4 and then goes out on port 3 to the non-OpenWrt router that direct it to the modem and the Internet.
  • Ports 3 and 4 are specifically configured just to sniff the packages: they do not have any IP address: see the configuration below.
  • Ports 1 and 2 are regular ports that can be accessed with the IP address of the router: they are used to access the router from the private network by HTTP or SSH. The WAN port is not used as the TP-WDR3600 is not performing any router activities.

NOTE: the TP-WDR3600 also provides WiFi for the private network.

This small diagram may help you understand:

+----------+     +---------------------+    +--------+   +-----------------+
| Internet |     |     TP-WDR3600     1|----| Switch |---| Private network |
+----------+     |       OpenWrt       |    +--------+   +-----------------+
     |           |                     |                           |
     |           |WAN: no connection  2|--               +-----------------+
 +--------+      |                     |  |              | Postgresql and  |
 | Router |------|3                   4|--               | web php server  |
 +--------+      +---------------------+                 +-----------------+

Here is the /etc/network configuration files of my TP-WDR3600:

config interface 'loopback'
        option ifname 'lo'
        option proto 'static'
        option ipaddr ''
        option netmask ''

config globals 'globals'
        option ula_prefix 'xxxx:xxxx:xxxx::/48'

config interface 'lan'
        option ifname 'eth0.1'
        option force_link '1'
        option type 'bridge'
        option proto 'static'
        option netmask ''
        option ip6assign '60'
        option dns ''
        option ipaddr ''
        option gateway ''
        option delegate '0'

config switch
        option name 'switch0'
        option reset '1'
        option enable_vlan '1'
        option mirror_source_port '0'
        option mirror_monitor_port '0'

config switch_vlan
        option device 'switch0'
        option vlan '1'
        option vid '1'
        option ports '0t 2 3'

config switch_vlan
        option device 'switch0'
        option vlan '2'
        option ports '0t 1'
        option vid '2'

config switch_vlan
        option device 'switch0'
        option vlan '3'
        option vid '3'
        option ports '0t 4'

config switch_vlan
        option device 'switch0'
        option vlan '4'
        option vid '4'
        option ports '0t 5'

config interface 'mon1'
        option proto 'none'
        option ifname 'eth0.3'

config interface 'mon2'
        option proto 'none'
        option ifname 'eth0.4'

config interface 'sniff'
        option proto 'static'
        option ifname 'eth0.3 eth0.4'
        option type 'bridge'

And here is the /etc/config/bandwidthd file:

config bandwidthd
	option dev	br-sniff
	option subnets		""
	option skip_intervals	0
	option graph_cutoff	1024
	option promiscuous	true
	option output_cdf	false
	option recover_cdf	false
	option filter		ip
	option graph		true
	option meta_refresh	150
	option pgsql_connect_string	"user = postgres dbname = bandwidthd host ="
	option sensor_id	"my_sensor_name"

doc/howto/bandwidthd.txt · Last modified: 2016/11/18 02:48 by jmlacroix