On 03/10/14(Fri) 14:46, Stefan Sperling wrote:
> The IPv6 source address selection algorithm breaks ties by performing a
> bitwise match of each candidate source address against the destination
> address. The longest matching source address wins, regardless of which
> interface the source address came from.
>
> In my carp setup, this is causing a problem.
>
> Consider the carp address 2001:DB8:10::14, which is configured on
> firewall A (carp master state) and firewall B (carp backup state),
> each of which has another address in the same prefix on a non-carp
> interface (A has 2001:DB8:10::1 and B has 2001:DB8:10::11).
>
> In this setup, connecting from A to B or from B to A via IPv6 is impossible.
> A will use 2001:DB8:10::14 as source address when it sends neighbour
> solicitations to B (2001:DB8:10::11). Since 2001:DB8:10::14 is a local
> address from B's point of view, B doesn't reply to neighbour solicitations
> sent by A. The only currently available workaround is to re-configure
> addresses in a way that outsmarts the longest match check such that a
> carp address always loses the tie. (Another workaround is to use IPv4
> which doesn't have this problem.)
>
> The hack below special-cases carp interfaces: If there is a tie, then a
> carp interface is not allowed to win even if it has a longer bitwise match.
> (The carp interface is in master state here -- carp interfaces in backup
> state are never considered for source addresses in the first place.)
>
> This hack makes communication between A and B work over IPv6 in the
> above scenario.
I think this hack makes sense. I'm really afraid of the carp tentacles,
but I don't think there's a better way of solving this problem right
now.
This change is similar to the "let's move the cloning route" hack for
IPv4, since it gives a higher ``priority'' to any non-carp interface
when selecting source addresses, right?
> I also considered another solution: Make carp backups treat their
> local carp address as a non-local address. However, this would
> be a much more invasive change and would also affect IPv4.
This is certainly not an easy change, and it definitively comes with its
own specific dragons, but I believe that it would remove a lot of hacks
in the stack.
> - if (matchcmp > 0) /* (8) */
> + if (matchcmp > 0) { /* (8) */
> +#if NCARP > 0
> + /*
[...]
> + */
> + if (ifp->if_type == IFT_CARP)
> + continue;
> +#endif
> goto replace;
> + }
What if oifp is also a carp interface? Is it possible? Shouldn't you
use the pattern of in_addprefix():
if (ifp->if_type == IFT_CARP &&
oifp->if_type != IFT_CARP)
continue;
Either way I'm ok with your diff.