Codementor Events

OpenWRT Rewiring

Published Nov 26, 2019

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.

Discover and read more posts from Sanchit Sharma
get started