Subject: IPv6 source address selection
From: Vincent Bernat <bernat@luffy.cx>
Date: Sat, 05 Feb 2011 23:58:47 +0100

Hello!

I am  currently using SixXs to  get IPv6 connectivity. I  have a "sixxs"
interface where I add IPv6 address. For example (on host):

4: sixxs@NONE: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1280 
    inet6 X::10/128 scope global 
       valid_lft forever preferred_lft forever
    inet6 X::5/128 scope global 
       valid_lft forever preferred_lft forever
    inet6 X::7/128 scope global 
       valid_lft forever preferred_lft forever
    inet6 X::11/128 scope global 
       valid_lft forever preferred_lft forever
    inet6 Y::2/64 scope global 
       valid_lft forever preferred_lft forever

On guest:

4: sixxs@NONE: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1280 
    inet6 X::7/128 scope global 
       valid_lft forever preferred_lft forever

With  this setup,  I have  no problem.   On each  vserver, I  declare an
interface  by  setting  /etc/vservers/AAAA/interfaces/1/ip to  the  IPv6
address and /etc/vservers/AAA/interfaces/1/dev  to "sixxs". Then, on the
server with IP X::7, if I initiate a connection to ipv6.google.com (with
netcat6), the source address is X::5. All fine.

I am trying to migrate to  native IPv6. In this case, IPv6 addresses are
set on eth0. I have something like this (on host):

2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qlen 1000
    inet6 X::5/64 scope global 
       valid_lft forever preferred_lft forever
    inet6 X::10/64 scope global 
       valid_lft forever preferred_lft forever
    inet6 X::7/64 scope global 
       valid_lft forever preferred_lft forever
    inet6 X::11/64 scope global 
       valid_lft forever preferred_lft forever
    inet6 X::2/64 scope global 
       valid_lft forever preferred_lft forever

On guest:

2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qlen 1000
    inet6 X::7/64 scope global 
       valid_lft forever preferred_lft forever

/etc/vservers/AAA/interfaces/1/dev   is  set  to   "eth0",  and   I  use
/etc/vservers/AAA/interfaces/1/prefix to tell that the prefix is /64.

Now,  if  X::7 initiate  a  connection  to  ipv6.google.com, the  source
address is X::5 (the first IPv6  address on the host). And this does not
work.

I have looked at tcp_v6_connect():

       if(ipv6_addr_any(&usin->sin6_addr)) {
               struct nx_info *nxi =  sk->sk_nx_info;

               if (nxi && nx_info_has_v6(nxi))
                       /* FIXME: remap lback? */
                       usin->sin6_addr = nxi->v6.ip;
               else
                       usin->sin6_addr.s6_addr[15] = 0x1;
       }

But I don't know what nxi->v6.ip should contain. Is there a way to force
a vserver to bind  INADDR_ANY to one of the IPv6 address  of the guest instead
of taking the first IPv6 address of the host?
-- 
I WILL NOT SPIN THE TURTLE
I WILL NOT SPIN THE TURTLE
I WILL NOT SPIN THE TURTLE
-+- Bart Simpson on chalkboard in episode 8F21