So, the promissed blog entry on setting up OpenWRT on a router with insufficient flash.
I had never used OpenWRT before and was curious to find how it would preform against Smoothwall, a linux distribution aimed at being an easy to use, cheap replacement for professional routers. I had set up both routers on a virtual machine host in a fast network and compared performance. OpenWRT by far outperformed the dated Smoothwall, given the same hardware, and I was quite impressed.
However, setting up OpenWRT on actual hardware was something new for me and I still had to get my bearings. Having done all that right now, I thought I'd give any Googler who finds his way onto my blog, the advantage of not having to learn all this themselves. Now, I realize that these how-tos invariably become cooking recipes, which people copy & paste into their computers, boil for a while and come up with the magic potion -- OpenWRT in a router, with no idea whatsoever as to how that was accomplished. Let's try to avoid that and go over some basics first.
To understand OpenWRT in a router, we must first understand that OpenWRT is a Linux-based open-source software package and that a Router is an embedded device:
- Linux-based open-source packages are basically bundles of programs, which were already created for another purpose beforehand. The challenge for the creators of these packages, is to mix these existing programs in the right combination to suit another purpose.
- Embedded devices, on the other hand are basically computers, which have been simplified to the greatest possible extent, in order to serve a particular purpose. The challenge for the creators of these embedded devices, is to produce the same functionality in the fewest cheap components possible.
These two factors make Linux in a Router an odd couple, but fortunately for us, the guys at OpenWRT already did all the heavy-lifting involved in squeezing their Linux programs into as small a package as possible.
The key advantage of OpenWRT over stock firmware that is supplied by the manufacturer of the embedded device, is that it is:
- Open source, meaning there are legal and legitimate ways to know what it actually does
- Made up off smaller parts for different purposes, which you can pick and choose
- Actually has very good performance as a router and contains many advanced features you might want to have in a router
For embedded devices, unless you are plugging your wires directly into the manufacturer's board diagnostic port, the only way to configure them, is to have almost all of the routers functions operating, so that you can connect to it over the network and run commands. This means, that if anything goes wrong with any of the core programs, you've ended up with a router that you cannot connect to to try to repair the problem or upgrade again, meaning it's bricked and you can go buy a new one. For this purpose, OpenWRT comes as a series of pre-built packages for most routers that have all the configuration to work properly. All you have to do to use them is to download the right one to your computer and then "upgrade" your router with this file. Nothing can go wrong because the package was designed specifically for your model and is known to work.
Having noted that OpenWRT does not work on just any router and also having noted that my suppliers do not import just any router either, my choice was the most generic Chinese product I could find on the market, which seemed to exist on OpenWRT's pages -- the TP-Link TL-MR3420.
As you can see on the picture (image courtesy of the OpenWRT wiki) this embedded device is indeed simplified, with barely anything other than the square CPU chip, set next to the rectangular Flash chip on the board. What I didn't realize was that the Flash itself has been minimized to a meagre 4 MB of NOR flash. In this atomic age, where the smallest USB key on the market contains several orders of magnitude more flash, TP-Link has ingeniously chosen to limit themselves to 4 MB. Now this may not make much sense to me and any western reader of this blog, but you have to realize, all of these circuits are manufactured in China, where their mentality on the issue is slightly different, and in some twisted way, 4 MB of flash is exactly the thing you want to put on this particular circuit.
Unfortunately for us, OpenWRT struggles to fit into 4 MB of flash. You can get the basic router into this package, but not for instance the browser based configuration interface, which most people take for granted.
So how do we beat this? Some people on the OpenWRT forum suggest soldering off the 4 MB flash chip and attaching a bigger chip, unfortunately I'm not that kind of an electronics expert and... as I recall even the more experienced people note -- this is a great way to produce a non-functioning piece of electronics.
Instead, there is an interesting opportunity. The TP-Link TL-MR3420 also has an USB port. With some skill, some luck and some effort, it should be possible to extend it's storage capacity with an USB key. Now at the time I have never done that before either and for most software projects I have seen, this kind of procedure would be quite complicated. Fortunately for us, OpenWRT was designed for these sorts of modifications and we don't even have to be programmers to adjust it in this manner.
One thing to understand about OpenWRT before we proceed, is that one of the steps taken, to ensure the package is as small as possible, is that the system in which the programs are stored within the package is compressed, like a ZIP file. The problem with storing programs and settings in this manner is that in order to use every last bit of space, the files are stacked very closely together and this means that if a program were to make an addition, say try to save a configuration item, it would have to move all the other programs to make room for this bit of information. To avoid this situation, OpenWRT uses a rather remarkable combination of filing systems. The first, called SquashFS contains all the programs like a big ZIP file and cannot be changed or have any additions made to it, the second is JFFS2 which does allow additions but doesn't compress as efficiently as the first one. They are combined in a way that all the pre-installed programs are in SquashFS and all the changes are contained in JFFS2. Because both systems are not equally efficient however, this means that the pre-installed programs take up less space, than the ones you install afterwards.
There is a package on the OpenWRT website, called an Image Builder. It is a tool, that can be used on a 64bit Linux computer, to generate the same packages that are otherwise available for download, but with whatever changes you desire. This generator, can add any OpenWRT program you choose, into the pre-installed package, making the end result fit into a small package better than it would if you had installed the same programs after flashing your router.
There are multiple versions of OpenWRT and if you are unfamiliar with open source programs, "stable" is what you are looking for. Open source programs tend to have versions which are tried and work called "stable" and a version called "bleeding edge" which contains the latest features the devlopers are working on. Although you may think that having the latest features is a good thing (and it may yet be if you want to help the developers with their development process), it is called "bleeding edge" for a reason -- if you use it, get ready to bleed -- or in other words, suffer from all the broken features which do not yet work properly. The stable version at the time I was writing this blog is "14.07 Barrier Breaker".
My router, the TP-Link TL-MR3420, has an ar71xx CPU, so the image builder for it can be found at:
You will also want to take a look at this resource to get you up to speed as to what you need to do with your computer in order to be able to run the image builder. I will assume you know how to come up with a 64bit Linux installation on your computer, that is a setup I would warmly recommend if you ever intend to do any sort of software hacking, it is practically a pre-requisite.
I've of course tried to run this image builder to create a package with the browser based configuration interface (called "luci"), but the result was too big. I did however, manage to create a package with everything needed to utilize an USB key for additional storage. The line I needed to use was:
make image PROFILE=TLMR3420 PACKAGES="kmod-scsi-core kmod-usb-core kmod-usb2 kmod-usb-storage block-mount kmod-fs-ext4 fdisk"...the package kmod-scsi-core is needed because of the way an USB key appears to Linux in this router, the kmon-usb-core, kmod-usb2 and kmod-usb-storage deal with support for an USB key as such, block-mount is a package needed to attach additional filing systems to your router, kmod-fs-ext4 is support for the filing system we are going to use on our USB key and fdisk is a tool we may have to use in order to find our USB key once it is connected.
This procedure created a sufficiently small binary that I was able to flash onto the router trough the "Firmware upgrade" interface. Go grab a cup of coffee and stay away from the computer until the upgrade process is complete, as panicking and interrupting the process will brick the router. Not forgetting to replug my ethernet cable so that my computer got the router's new IP, and not forgetting that our new router software doesn't have a web interface yet, I connected to the router using telnet:
At this point, it is useful to input some basic settings into our router. It doesn't have a web interface yet so we won't bother doing a lot, but should something happen to the USB key attached to the router, it will fall back to the state that we configure now, so it would be worthwhile to configure a password (using the command "passwd") and a wired subnet (using the commands "uci set network.lan.ipaddr=a.b.c.1", replace a.b.c with a subnet of your choosing, and "uci commit"). As soon as you set a password, the router will reconfigure itself to disable telnet access, and enable SSH, which is a lot more secure but doesn't work without a password, this procedure may take a few seconds so do not panic if you cannot reconnect to your router straightaway. To connect using SSH use "ssh firstname.lastname@example.org". To continue it may be wise to reboot your router to make sure it will take into account all the settings we have entered thus far. Use the "reboot" command.
The next step is to take a USB key you are willing to sacrifice for this procedure, connect it to your desktop and format it as EXT4. Needless to say this can only be done on a Linux machine. When you are finnished, connect the newly formatted USB key to the router. What we are going to do next is copy the existing files from the router to the USB key, make the router use the USB key and reboot it so that it starts up from that USB key, where there is additional free space.
However, there is something important to note at this point. Flash. I've mentioned it before. What is Flash? Why is it called Flashing, what does that mean? Flash is very simply a technology to permanently store data in a chip. The now popular SSD drives run on flash, but you may already be more familiar with flash memory as such in various phone and camera SD cards, USB keys, etc. Flashing, is simply the act of recording data onto these flash chips. This is actually some kind of convoluted procedure that an SSD or USB key makes completely seamless and automatic, but it actually involves erasing the chip and then writing new information into it. There are multiple technologies in use which are all called Flash, most significantly NOR flash -- more expensive, but faster, typically used to store programs in embedded devices, and NAND flash -- slower, but cheaper and usually much bigger, normally used to store data, typically used in USB keys.
The 4 MB chip in our router is NOR and the USB key I used is NAND. I should therefore want to use the 4 MB chip as much as I can and only resort to the USB key for when I run out of space. I decided to re-use the same system that OpenWRT uses to keep it's changes and it's core programs seperate -- and keep all the pre-installed programs on the fast NOR flash, and all my changes on the slower, but bigger USB key. So instead of copying all the router files to the USB key, I only copy the changes kept in the "overlay" folder. Keep in mind that if the USB key is not the first disk on the router, it will not be "sda1", if necessary use the "fdisk" command to find the right device.
mkdir /mnt/sda1This connects our USB key to the folder called /mnt/sda1, that we have created for this purpose.
mount /dev/sda1 /mnt/sda1
tar -C /overlay -cvf - . | tar -C /mnt/sda1 -xf -This is a convoluted way to copy files, that makes sure that they written as they were read and not altered in any way in the process, using a command normally used to make backups.
Add to the "/etc/config/fstab" file:
config mountThis makes our USB key (at /dev/sda1) be used to provide the /overlay folder, with a few additional options that will make the flash in the USB key wear out less in the long run.
option target /overlay
option device /dev/sda1
option fstype ext4
option options rw,sync,noatime
option enabled 1
option enabled_fsck 0
Finally, reboot the router with the "reboot" command and observe as the router reloads, fetching information from the USB key as necessary. Once you have completed this step, you can connect to the router and install additional software. If you use the "df -h" command, you will be able to see the amount of free space you have available. If the procedure has worked, there should be a few GB of free space (depending on the size of your USB key, mine is 8 GB), if not there will be around 640k of free space.
Assuming you have successfully secured enough free space from your USB key in the previous step, you may now proceed to install the browser based interface and finish configuring your router trough a browser:
opkg updateThis command retrieves a fresh list of downloadable programs for your router
opkg install luciThis command will automatically download and install the browser based interface "luci"
/etc/init.d/uhttpd startThis command will start up LUCI, if this works you can continue to the next step
/etc/init.d/uhttpd enableThis command enables LUCI startup at each boot. Don't do this if it doesn't start manually in the previous step, because that may result in a bricked router.
After this step, configure the router as you like. When the USB light stops flashing, you can reboot the router by unplugging the power as you desire.
Try to avoid installing things you do not need, as there is no "uninstall" feature in OpenWRT, other than to erase everything and start over. However as you have several GB of free space and most programs only take a few KB (two orders of magnitude less), installing things you do need should not be a problem.