Configuring OpenWRT on an NSLU2

From SixXS Wiki
Jump to: navigation, search

Problems have been reported setting up aiccu and radvd together on OpenWRT [[1]]. This page recounts what worked for me on a Linksys NSLU2 running OpenWRT 10.03.1-RC6. The NSLU2 offers one just wired ethernet port and two USB ports.

The general setup is a small home network connected to the ISP via a first-generation Apple Time Capsule. The machines on the network are Macs and Linux boxes and, apart from a fixed IP, there's nothing special about the network. The ISP doesn't offer IPv6, and I wanted world-routable static IPs. I wanted to set up the NSLU2 as simply as possible, so I turned off anything I didn't need or didn't understand.

I started by compiling OpenWRT 10.03.1-RC6.

Compiling OpenWRT

(For another account of compiling OpenWrt for this purpose, see [[2]] -- I just want to relate here what I did, specifically for OpenWRT 10.03.1-RC6 and the NSLU2.)

The first step is to get a basic version of OpenWRT with IPv6 support. To do this, I followed the directions at except for one thing: in the section entitled "Updating Feeds" it suggests installing all feeds with the command: ./scripts/feeds install -a. I don't do this.

Use menuconfig to select the target system and the target profile. Then select kmod-ipv6.

 Target System >  Intel IXP4xx
 Target Profile > Linksys NSLU2
 Kernel Modules > Network Support > kmod-ipv6

Make sure this works: compile and install OpenWrt onto the NSLU2. You should get Link-Local IPv6 addresses appearing in the ifconfig listing:

 root@OpenWrt:/# ifconfig
 br-lan    Link encap:Ethernet  HWaddr 00:1A:70:94:D1:ED  
         inet addr:  Bcast:  Mask:
         inet6 addr: fe80::21a:70ff:fe94:d1ed/64 Scope:Link
         RX packets:324 errors:0 dropped:0 overruns:0 frame:0
         TX packets:44 errors:0 dropped:0 overruns:0 carrier:0
         collisions:0 txqueuelen:0 
         RX bytes:106149 (103.6 KiB)  TX bytes:4881 (4.7 KiB)
 eth0      Link encap:Ethernet  HWaddr 00:1A:70:94:D1:ED  
         RX packets:326 errors:0 dropped:0 overruns:0 frame:0
         TX packets:45 errors:0 dropped:0 overruns:0 carrier:0
         collisions:0 txqueuelen:100 
         RX bytes:106425 (103.9 KiB)  TX bytes:4971 (4.8 KiB)
 lo        Link encap:Local Loopback  
         inet addr:  Mask:
         inet6 addr: ::1/128 Scope:Host
         UP LOOPBACK RUNNING  MTU:16436  Metric:1
         RX packets:0 errors:0 dropped:0 overruns:0 frame:0
         TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
         collisions:0 txqueuelen:0 
         RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

OK, so far, so good. Now to install the packages needed for the sixxs tunnel and for the radvd router advertisement daemon:

 $ ./scripts/feeds install aiccu radvd
 Installing package 'aiccu'
 Installing package 'ntpclient'
 Installing package 'radvd'

Next, use menuconfig to include them in the build:

 IPv6 > aiccu
 IPv6 > radvd

A number of other packages are automatically included in the build. Compile and install, as before.

The aiccu and radvd packages include startup code so that the services will automagically be launched at boot time. They should fail to launch, however, (and may leave error messages), because they haven't yet been configured.

Obvious Stuff

I had plenty of trouble getting the tunnel and radvd to work properly together and so I wanted to eliminate as many confounding factors as possible. The first thing I did was to turn off the built-in DNS/DHCP server dnsmasq, which is enabled in the default build -- my local network already has these services.

Turn Off dnsmasq

 root@OpenWrt:# /etc/init.d/dnsmasq stop
 root@OpenWrt:# /etc/init.d/dnsmasq disable

The next thing I did was to disable the IPv6 firewall.

Turn Off IPv6 Firewall

In the file /etc/config/firewall, look for the two lines:

 # Uncomment this line to disable ipv6 rules
 #       option disable_ipv6     1

and uncomment the second line. This will disable the IPv6 firewall.

Enable IPv6 Forwarding

Find this line in /etc/sysctl.conf and uncomment it:

 # net.ipv6.conf.all.forwarding=1

The Core of the Problem

Recall that I wanted the NSLU2 to be as self-configuring as possible. In summary, what I wanted was for br-lan to pick up regular IPv4 information using DHCP, to pick up the relevant IPv6 information from radvd, and finally, of course, to function as an IPv6 tunneling router. That's what I got, eventually.

You might imagine that the network settings for IPv4 and IPv6 are independent of one another, but you'd be wrong. In OpenWrt, the behavior of radvd on the network interface br-lan is affected by the protocol setting static or dhcp. By default, the interface setting accept_ra [[3]] is false for an interface with a static protocol and true if the chosen protocol is dhcp.

If accept_ra is false (the default if the protocol setting is left at static), then radvd will not have any effect on br-lan. However, if accept_ra is true, (the default if the protocol setting is dhcp), then radvd will do two things: it will give br-lan an IPv6 address within the subnet it is advertising, (a good thing, IMHO), but it will also tell the NSLU2 to route all IPv6 packets through br-lan by default. Thus a packet routed from elsewhere on the network into the NSLU2 will actually be routed back to the port -- br-lan -- it came into the NSLU2 on. This is Not A Good Thing, for sure, and I think the cause of problems referred to elsewhere.

Sysctl Settings

To see what might actually be happening, and to fix it, take a look at the sysctl entries relating to IPv6 and br-lan. You can use the command

 sysctl -a

to list all sysctl settings. Here is an extract of what you see if accept_ra is false: = 0

If accept_ra is true you'll get this: = 2

(See [[4]] or similar for an explanation of these settings.) What this means is that if the protocol is static, br-lan will ignore the periodic IPv6 router advertisements coming from radvd. That is unfortunate, but it isn't fatal. It's unfortunate because it means that you must manually give br-lan an IPv6 ip number within the subnet to be advertised by radvd.

If the protocol is dhcp, then br-lan will act on the router advertisements, automatically acquiring an IPv6 ip number within the subnet advertised. Unfortunately -- and fatally -- it will also acquire a default route which would be right for other devices on the network, but which is not right for the NSLU2 which is acting as a router, as it causes the forwarding loop already described. Happily, there is another setting in sysctl that controls whether a default route should be accepted from a router advertisement.

The setting: = 0

will instruct the interface not to accept default router information from radvd, even while it does accept an IPv6 ip number. This is exactly the behavior I want.

The Settings


Add this line to turn off default route acceptance on br-lan:


Turn on dhcp for eth0, making the file contents look like this:

 # Copyright (C) 2006
 config interface loopback
       option ifname   lo
       option proto    static
       option ipaddr
       option netmask
 config interface lan
       option ifname   eth0
       option type     bridge
       option proto    dhcp         


Insert your tunnel details here. This is for an AYIYA tunnel.

 config aiccu
 	option username	'<your username>'
 	option password	'<your password>'
 	option protocol		
 	option server		
 	option interface	'sixxs'
 	option tunnel_id	
 	option requiretls	'0'
 	option defaultroute	'1'
 	option nat		'1'
 	option heartbeat	'1'


Insert your subnet details here.

 config interface
       option interface        'lan'
       option AdvSendAdvert    1
       option AdvManagedFlag   0
       option AdvOtherConfigFlag 0
       list client             
       option ignore           0
 config prefix
       option interface        'lan'
       # If not specified, a non-link-local prefix of the interface is used
       list prefix             '<your subnet prefix>/64'
       option AdvOnLink        1
       option AdvAutonomous    1
       option AdvRouterAddr    0
       option ignore           0  
 config route
       option interface        'lan'
       list prefix             
       option ignore           1
 config rdnss
       option interface        'lan'
       # If not specified, the link-local address of the interface is used
       list addr               
       option ignore           1
 config dnssl
       option interface        'lan'
       list suffix             
       option ignore           1

Notice that the ignore flag is true for route, rdnss and dnssl, so they are ignored -- I haven't figured them out yet. Also notice that the name of the interface you specify here is "lan", and not "br-lan" -- the "br-" part is added automagically.

Try it out

Make sure your NSLU2's clock is nearly right, or the tunnel will collapse. Turn on aiccu and radvd using the commands:

 /etc/init.d/aiccu start
 /etc/init.d/radvd start

and check that everything is working. It should be :)

The aiccu and radvd packages include code to ensure that each service is automatically enabled to start on boot.

This has been working very well for me. I hope you find the account of it useful.