OpenWRT Rewiring
This post is about making an OpenWRT image with the usb dongle support.
We, as a part of our kit that collects and sends data of energy meters over then net required to use routers in the solution along with the raspberry.
We settled on TP-LINK MR3020 with usb dongle support. Now, there is always an issue with usb dongles which cause them to lose connectivity and they go into a hung state which can be resolved by just plugging out an plugging in the dongle back. But in a system that has to be deployed, has to work without manual intervention, that can't be a solution. So we needed more control over the router, and hence OpenWRT.
OpenWRT has a pretty decent documentation wiki of its own, but it is a little scattered, and this post is intended to describe making of an image with the 3g dongle usage in mind. The steps listed here should work with pretty much any router just by replacing a few words in the command which I will highlight as and when required.
(This is the link to the OpenWRT documentation on how to make a custom image. - http://wiki.openwrt.org/doc/howto/obtain.firmware.generate )
Firstly, check the architecture of your router and download the appropriate image builder from here (go to the folder of your router's architecture and download the ImageBuilder archive. For TLMR3020, I went to ar71xx)- http://downloads.openwrt.org/barrier_breaker/14.07/
Extract the archive. Go to the extracted folder (for me it was OpenWrt-ImageBuilder-ar71xx_generic-for-linux-x86_64). Configure the package repositories in the repositories.conf file. My repositories file looked like (copied from the OpenWRT wiki)
src/gz barrier_breaker_base http://downloads.openwrt.org/barrier_breaker/14.07/ar71xx/generic/packages/base
src/gz barrier_breaker_luci http://downloads.openwrt.org/barrier_breaker/14.07/ar71xx/generic/packages/luci
src/gz barrier_breaker_management http://downloads.openwrt.org/barrier_breaker/14.07/ar71xx/generic/packages/management
src/gz barrier_breaker_oldpackages http://downloads.openwrt.org/barrier_breaker/14.07/ar71xx/generic/packages/oldpackages
src/gz barrier_breaker_packages http://downloads.openwrt.org/barrier_breaker/14.07/ar71xx/generic/packages/packages
src/gz barrier_breaker_routing http://downloads.openwrt.org/barrier_breaker/14.07/ar71xx/generic/packages/routing
src/gz barrier_breaker_telephony http://downloads.openwrt.org/barrier_breaker/14.07/ar71xx/generic/packages/telephony
## This is the local package repository, do not remove!
src imagebuilder file:packages
The command to build the image is
make image PROFILE=XXX PACKAGES="pkg1 pkg2 pkg3 -pkg4 -pkg5 -pkg6" FILES=files/
PROFILE
Check the name of profile for your router, most likely it would be the router's name. For me it was TLMR3020. You can check the list of available profiles by running <make info> command in the extracted folder. The list of profiles available for ar71xx are - http://pastebin.com/WbudpBDJ.
PACKAGES
Following are the packages required for the usb dongle to work and for luci (the web interface. You can exclude it if just ssh access is fine for you)
comgt kmod-usb-serial kmod-usb-serial-option kmod-usb-serial-wwan usb-modeswitch kmod-usb-storage block-mount kmod-fs-vfat kmod-nls-cp437 kmod-nls-iso8859–1 luci-proto-3g luci
FILES
This is the important part for the image to work out of the box. For wireless and usb dongle to work as soon as you install the image (this is important for those who are update the firmware over remote access, as was the case for me), some files need to be included in the image. The way to include the files is extremely simple. You just make a directory in which you include the files exactly in the same structure as you want them in the router and pass the path of that directory. I included the following files in my directory -
/etc/chatscripts/3g.chat
ABORT BUSY
ABORT 'NO CARRIER'
ABORT ERROR
REPORT CONNECT
TIMEOUT 10
"" "AT&F"
OK "ATE1"
OK 'AT+CGDCONT=1,"IP","$USE_APN"'
SAY "Calling UMTS/GPRS"
TIMEOUT 30
OK "ATD*99#"
CONNECT ' '
The second last line might need to be changed according to your ISP.
/etc/config/firewall
config defaults
option syn_flood 1
option input ACCEPT
option output ACCEPT
option forward REJECT
# Uncomment this line to disable ipv6 rules
# option disable_ipv6 1
config zone
option name lan
list network 'lan'
option input ACCEPT
option output ACCEPT
option forward ACCEPT
config zone
option name wan
list network 'wan'
list network 'wan6'
option input REJECT
option output ACCEPT
option forward REJECT
option masq 1
option mtu_fix 1
config forwarding
option src lan
option dest wan
# We need to accept udp packets on port 68,
# see https://dev.openwrt.org/ticket/4108
config rule
option name Allow-DHCP-Renew
option src wan
option proto udp
option dest_port 68
option target ACCEPT
option family ipv4
# Allow IPv4 ping
config rule
option name Allow-Ping
option src wan
option proto icmp
option icmp_type echo-request
option family ipv4
option target ACCEPT
# Allow DHCPv6 replies
# see https://dev.openwrt.org/ticket/10381
config rule
option name Allow-DHCPv6
option src wan
option proto udp
option src_ip fe80::/10
option src_port 547
option dest_ip fe80::/10
option dest_port 546
option family ipv6
option target ACCEPT
# Allow essential incoming IPv6 ICMP traffic
config rule
option name Allow-ICMPv6-Input
option src wan
option proto icmp
list icmp_type echo-request
list icmp_type echo-reply
list icmp_type destination-unreachable
list icmp_type packet-too-big
list icmp_type time-exceeded
list icmp_type bad-header
list icmp_type unknown-header-type
list icmp_type router-solicitation
list icmp_type neighbour-solicitation
list icmp_type router-advertisement
list icmp_type neighbour-advertisement
option limit 1000/sec
option family ipv6
option target ACCEPT
# Allow essential forwarded IPv6 ICMP traffic
config rule
option name Allow-ICMPv6-Forward
option src wan
option dest *
option proto icmp
list icmp_type echo-request
list icmp_type echo-reply
list icmp_type destination-unreachable
list icmp_type packet-too-big
list icmp_type time-exceeded
list icmp_type bad-header
list icmp_type unknown-header-type
option limit 1000/sec
option family ipv6
option target ACCEPT
# include a file with users custom iptables rules
config include
option path /etc/firewall.user
/etc/config/network
config interface 'loopback'
option ifname 'lo'
option proto 'static'
option ipaddr '127.0.0.1'
option netmask '255.0.0.0'
config globals 'globals'
option ula_prefix 'fd66:0dee:5f2c::/48'
config interface 'lan'
option force_link '1'
option type 'bridge'
option proto 'static'
option ipaddr '192.168.1.1'
option netmask '255.255.255.0'
option ip6assign '60'
option _orig_ifname 'eth0 wlan0'
option _orig_bridge 'true'
option ifname 'eth0'
config interface 'wan'
option _orig_ifname 'radio0.network1'
option _orig_bridge 'false'
option proto '3g'
option device '/dev/ttyUSB0'
option service 'gprs_only'
option apn 'internet'
config wifi-device 'radio0'
option type 'mac80211'
option channel '11'
option hwmode '11g'
option path 'platform/ar933x_wmac'
option htmode 'HT20'
option txpower '30'
option country 'US'
config wifi-iface
option device 'radio0'
option mode 'ap'
option ssid 'OpenWRT-Wifi'
option encryption 'none'
option wmm '0'
option network 'lan'
Last three files are just copied from the router once all the options had been configured.
The next 3 files are two fix the dongle reset problem.
What we figured out was that every now and then the dongle got reset and lost its connection which can be solved by plugging out and plugging back the dongle. To emulate this a script is there by name of donglereset which checks if the internet is not working it switches the usb power off and on again after a couple of seconds. This is done by switching off the GPIO pin on the router. This pin might be different for different routers. The current script works for TLMR3020 with pin 8 for usb. The other two files are for initiating the cron and one crontab which runs the cron every 15 minutes.
/root/donglereset
#!/bin/bash
wget -s http://google.com
if [[ $? -eq 0 ]]; then
echo "Online"
else
echo "Offline"
ifdown wan
# turn off USB power
echo 0 > /sys/devices/virtual/gpio/gpio8/value
# let things settle
sleep 2
# turn on USB power
echo 1 > /sys/devices/virtual/gpio/gpio8/value
# restart the interface
ifup wan
fi
/etc/crontabs/root
*/15 * * * * ash /root/donglereset
/etc/init.d/S60cron
#!/bin/sh
# start crond
/usr/sbin/crond -c /etc/crontabs
All these files are to be included in a directory files within the extracted folder and with the same directory structure as mentioned.
MAKING IMAGE
Now, run the make image command. For me, it was
sudo make image PROFILE=TLMR3020 PACKAGES="comgt kmod-usb-serial kmod-usb-serial-option kmod-usb-serial-wwan usb-modeswitch kmod-usb-storage block-mount kmod-fs-vfat kmod-nls-cp437 kmod-nls-iso8859–1 luci-proto-3g luci" FILES=files/
You now will have the image in bin folder of the extracted folder in the directory name of your architecture. Mine's name was openwrt-ar71xx-generic-tl-mr3020-v1-squashfs-factory.bin. You can now use upload this image via the firmeware upgrade option in the router.