6LoWPAN for Bluetooth low energy on OpenWRT

image description

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.

Installation of required software

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

Fetch the source code of OpenWRT

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.

Configure the build and compile

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

Enable the Linux 3.18 kernel for the brcm47xx target

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):

cd ~/openwrt/target/linux/brcm47xx

Edit the target Makefile (for example, in vim) to enable kernel 3.18:

vim Makefile

Replace the 3.14 KERNEL_PATCHVER with 3.18. image description

Update and install feeds

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.

Configure the build

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:

make menuconfig

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. image description

Target system

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). image description image description image description

Target profile

Change the target profile to the following: Broadcom SoC, all Ethernet, BCM43xx WiFi (wl, proprietary). image description image description image description

Target images

Verify that squashfs is selected as target image for the build. image description image description

Base system

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. image description image description

Kernel modules -> Other modules

Enable kmod-bluetooth and kmod-bluetooth_6lowpan in the Kernel modules->Other modules submenu. image description image description image description image description

Kernel modules -> USB Support

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. image description image description image description image description image description image description


In the Libraries submenu enable bluez-libs. image description image description


Finally, enable the bluez-utils in the Utilities submenu. image description image description

The configuration is now done. Here is a summary of the modules that must be enabled:

  • Target System:
  • Broadcom BCM47xx/53xx (MIPS)
  • Target Profile:
  • Broadcom SoC, all Ethernet, BCM43xx WiFi (wl, proprietary)
  • Target Images:
  • squashfs
  • Base System:
  • block-mount
  • Kernel modules -> Other Modules:
  • kmod-bluetooth
  • kmod-bluetooth_6lowpan
  • Kernel modules ->USB Support:
  • kmod-usb-core
  • kmod-usb-ohci
  • kmod-usb-storage
  • kmod-usb2
  • Libraries:
  • bluez-libs
  • Utilities:
  • bluez-utils


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.

Installing the custom build on the router

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:

  1. Unplug the power cord from the router

  2. Hold down the “Reset” button when plugging in the power cord again. The router will now boot up in a recovery mode, starting an FTP server. We will connect to this FTP server to upload the new firmware.

  3. Issue the following commands:

    sudo ifconfig eth0

If ping replies, we have connection to the router, and we can proceed by opening up an FTP connection. 4. Connect to the FTP server by issuing the following commands:

    cd ~/openwrt/bin/brcm47xx
    tftp> mode binary
    tftp> put openwrt-brcm47xx-generic-squashfs.trx
  1. 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.

  2. 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:


image description

Connecting to IPv6-enabled BLE devices

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.

  1. 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
  2. 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)

image description

  1. 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. image description

  1. 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
        < LE 00:DD:F6:FF:20:DD handle 72 state 1 lm MASTER

image description

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.

image description

  1. 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):

MAC: 00:DD:F6:FF:20:DD

IPV6: fe80::2DD:F6ff:feFF:20DD

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.

image description

PING-PONG success!


ping6 command says “connect: Network unreachable”

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

    image description

  • 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

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.