OpenWRT is one of the most popular open source Linux-based router firmware alternatives for commodity routers. From kernel 3.17, Linux has supported 6LoWPAN for Bluetooth low energy (BLE) through the new kernel module bluetooth_6lowpan. The trunk version of OpenWRT has added kernel 3.18 support for most of its target platforms already, which indirectly adds the bluetooth_6lowpan kernel module that is required to enable IPv6 over BLE. This makes OpenWRT a perfect choice to explore IPv6 over Bluetooth low energy in a router environment.
In this blog, I’m going to explain how to compile a custom version of OpenWRT with the bluetooth_6lowpan kernel module for the ASUS RT-N16 router. As OpenWRT is supported on a wide range of routers, you can probably use this blog as a starting point for other routers too.
I chose to compile the OpenWRT firmware on an Ubuntu system. It might be possible to compile the firmware on other systems as well, maybe even on Windows, but the instructions in this tutorial apply to Ubuntu only.
Before we start compiling the OpenWRT firmware, we must install a few tools that are required to succeed with the build. Running the following command in a terminal will install what is needed.
sudo apt-get install build-essential subversion libncurses5-dev zlib1g-dev \ gawk gcc-multilib flex git-core gettext gcc binutils bzip2 \ python perl make unzip libz-dev tftp
Now it is time to fetch the trunk version of OpenWRT. I have chosen to use GIT and not SVN, but if you prefer SVN, feel free to use that instead. When using GIT:
git clone git://git.openwrt.org/openwrt.git
When using SVN:
svn co svn://svn.openwrt.org/openwrt/trunk/
I used GIT, and it cloned the repository into a new folder called openwrt. I placed this under my home folder: /home/glba/openwrt.
The next step is to modify the kernel version used for our target, and to complete the menuconfig of OpenWRT before we can start building the new image. The build target depends on the model and brand of the router. The target for the ASUS RT-N16 router is brcm47xx according to the list found on http://wiki.openwrt.org/toh/start#asus
When the target name has been determined, navigate to the target folder and activate the 3.18 kernel in the build. Issue the following command (assuming that the OpenWRT source code is located in ~/openwrt):
Edit the target Makefile (for example, in vim) to enable kernel 3.18:
Replace the 3.14 KERNEL_PATCHVER with 3.18.
Go back to the root directory of the repository. Then update and install the following OpenWRT feeds:
cd ~/openwrt ./script/feeds update –a ./scripts/feeds install libexpat bluez-utils bluez-libs
If you would like to have a graphical web interface like LUCI on the router, this is the stage in the build process where it can be added. You can always go back to this stage to make more packages available for your build later. You must then enable them in the menuconfig and compile again.
There are just a few modules that need to be activated to get OpenWRT up and running with 6LoWPAN and IPv6 over Bluetooth low energy. If you are not familiar with the menuconfig interface, I have attached some screenshots below of the various modules that must be activated.
To initiate the menuconfig, run the following command in the root folder of the repository:
Sometimes an error message will pop up, as shown in the screenshot below. For me, this was caused by the Ubuntu system that opened up a terminal emulator window which was slightly too small for menuconfig, so it could not render its beautiful ncurses TUI. This was easy to fix by slightly increasing the size of the window.
When the menuconfig is up and running, it is time to start configuring the build. For those that are not familiar with kernel configuration, here are some tips: ENTER will go into a submenu, ESC will go back, and pressing SPACE once or twice will enable a module. To quit and save, press ESC multiple times until you are prompted to either save the configuration or quit without saving.
By default, OpenWRT will select the AR7xx/AR9xx target system. You must change this to brcm47xx. Select the MIPS variant for the ASUS RT-N16, Broadcom BCM47xx/53xx (MIPS).
Change the target profile to the following: Broadcom SoC, all Ethernet, BCM43xx WiFi (wl, proprietary).
Verify that squashfs is selected as target image for the build.
Enable block-mount from the base system submenu. This is not required, but can be very handy if you want to mount a USB flash drive to the router for copying files or to extend the file system later.
Enable kmod-bluetooth and kmod-bluetooth_6lowpan in the Kernel modules->Other modules submenu.
Enable kmod-usb-core if it is not already enabled. Also enable kmod-usb-ohci, kmod-usb-storage, and kmod-usb2 in the Kernel modules->USB Support submenu.
In the Libraries submenu enable bluez-libs.
Finally, enable the bluez-utils in the Utilities submenu.
The configuration is now done. Here is a summary of the modules that must be enabled:
After pressing ESC multiple times and saving the configuration when prompted, it is time to compile. To speed up compilation a bit, configure the –j flag with the number of cores your computer has +1. My computer has two cores, so my –j flag will be set to 3.
Run the following command to start the compilation:
make V=s –j3
After 4-5 cups of coffee, it will eventually finish. (For me it took about an hour.) The result of the build is found under openwrt/bin/brcm47xx.
If the router still has its manufacturer ASUS firmware, it is not possible to upgrade the firmware through the ASUS router web interface. The OpenWRT firmware we have built is not recognized as a valid firmware binary. To work around this, use tftp to transfer the image over to the router. The guide located at http://wiki.openwrt.org/toh/asus/rt-n16 gives the following description how to do it:
Issue the following commands:
sudo ifconfig eth0 192.168.1.15 ping 192.168.1.1
If ping replies, we have connection to the router, and we can proceed by opening up an FTP connection.
Connect to the FTP server by issuing the following commands:
cd ~/openwrt/bin/brcm47xx tftp 192.168.1.1 tftp> mode binary tftp> put openwrt-brcm47xx-generic-squashfs.trx
After the firmware is uploaded, the router will automatically install the firmware. Wait up to 5 minutes, then unplug the power to the router and plug it in again.
When the router is booted up and we have received an IP address from the router, we can use telnet to log into the router:
As the router is now running on the 3.18 kernel with bluetooth_6lowpan and usb kernel modules, we can set up an IPv6 connection over BLE.
Enable 6LoWPAN over BLE: Plug in the BLE dongle into the USB port on the ASUS router. Then issue the following commands:
root@OpenWrt:/# modprobe bluetooth_6lowpan root@OpenWrt:/# echo 35 > /sys/kernel/debug/bluetooth/6lowpan_psm
Scan for BLE devices to figure out the Bluetooth MAC address we want to connect to:
root@OpenWrt:/# hcitool lescan LE Scan ... 00:8F:00:C4:EC:41 GLBAClient 00:8F:00:C4:EC:41 (unknown) 00:DD:F6:FF:20:DD GLBAServer 00:DD:F6:FF:20:DD (unknown)
Select one of the devices from the scan and connect to it using the current connect mechanism for bluetooth_6lowpan. The bluetooth_6lowpan module exposes a control interface through the debug file system, which allows to initiate IPv6 connections over BLE.
Issue the following command to connect to your device (replace the MAC address with the one of the device you want to connect to):
echo "connect 00:DD:F6:FF:20:DD 1" > /sys/kernel/debug/bluetooth/6lowpan_control
The following image shows my IPv6 enabled Development Kit (PCA10028) running a CoAP server. The LED1 indicates that it is advertising.
Verify that the BLE device is connected. When the previous connect command returns, we can monitor whether the BLE connection is successful. Issue the following command to see the list of connected devices:
root@OpenWrt:/# hcitool con Connections: < LE 00:DD:F6:FF:20:DD handle 72 state 1 lm MASTER
It turns out that the device is connected, and this is also confirmed by the Development Kit (following image). The LED1 is now turned off, indicating that advertisement has stopped, and LED2 is lit. This indicates that the kit is in a connection.
The bt0 interface is now up and running and our Development Kit is connected. Let’s ping it! Do the conversion of the Bluetooth MAC address into an IPv6 address (using the link-local prefix fe80):
Then ping the device with the following command (replace the IPv6 address with your own):
root@OpenWrt:/# ping6 fe80::2DD:F6ff:feFF:20DD%bt0
Note: The %bt0 at the end of the IPv6 address tells ping6 that it should use link-local addresses on the bt0 interface, not any of the other interfaces. Each interface uses distinct link-local addresses for its connected devices. Explicitly specifying to use bt0 tells ping6 that we want to use the link-local address on this interface.
This problem can occur if the L2CAP CoC connection has not come up during connection. In this case, verify two things:
Verify that a btX device has appeared. We have confirmed that the Bluetooth device is in a connection (hcitool con), so the next thing to verify is whether the L2CAP CoC connection has come up successfully and whether an IPv6 link is up and has created a btX interface. This can be verified by issuing the following command:
root@OpenWrt:/# ifconfig bt0
If the btX interface does not show up, verify that you set the correct PSM value in /sys/kernel/debug/bluetooth/6lowpan_control. The value should be set to 35. Verify this by doing a cat on the file:
root@OpenWrt:/# cat /sys/kernel/debug/bluetooth/6lowpan_psm 35
If the value is not 35, repeat steps 1 and 3 of the section “Connecting to IPv6-enabled BLE devices”. This should bring up the btX interface.