Subject: Re: [vserver] IPv6 source address selection
From: Bruno Prémont <bonbons@linux-vserver.org>
Date: Sun, 6 Feb 2011 00:57:44 +0100

Hello Vincent,

What kernel&linux-vserver patch versions are you running on?

On Sat, 05 February 2011 Vincent Bernat <bernat@luffy.cx> wrote:
> 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.

How many interfaces with IPv6 addresses do you have on your host, what
does the routing look like?
It could be caused by IPv6's approach of first looking up a route to the
target host and only when outbound interface is determined it does choose
a source address.
Though in that case it would still have expected source address, just go
to the wrong interface.

But I'm not sure I understand your setup and what exactly is failing...


> 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?

It should definitely only take one of the addresses available to guest and
none of the others that may exist on host (though for a multi-homed system
this may cause routing via wrong outbound interface, work-around is to trigger
rerouting via ip6tables). If no guest address is available it is expected to
fail with no route to host.

Bruno