On Tue, Oct 07, 2014 at 01:50:12PM +0200, Martin Pieuchot wrote:
> 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.

Makes sense and works for me.

Does anyone else have an opinion about this?

Index: in6.c
===================================================================
RCS file: /cvs/src/sys/netinet6/in6.c,v
retrieving revision 1.138
diff -u -p -r1.138 in6.c
--- in6.c       12 Jul 2014 18:44:23 -0000      1.138
+++ in6.c       17 Oct 2014 09:40:12 -0000
@@ -2027,8 +2027,26 @@ in6_ifawithscope(struct ifnet *oifp, str
                        }
                        tlen = in6_matchlen(IFA_IN6(ifa), dst);
                        matchcmp = tlen - blen;
-                       if (matchcmp > 0) /* (8) */
+                       if (matchcmp > 0) { /* (8) */
+#if NCARP > 0
+                               /* 
+                                * Don't let carp interfaces win a tie against
+                                * the output interface based on matchlen.
+                                * We should only use a carp address if no
+                                * other interface has a usable address.
+                                * Otherwise, when communicating from a carp
+                                * master to a carp slave, the slave won't
+                                * respond since the carp address is also
+                                * configured as a local address on the slave.
+                                * Note that carp interfaces in backup state
+                                * were already skipped above.
+                                */
+                               if (ifp->if_type == IFT_CARP &&
+                                   oifp->if_type != IFT_CARP)
+                                       continue;
+#endif
                                goto replace;
+                       }
                        if (matchcmp < 0) /* (9) */
                                continue;
                        if (oifp == ifp) /* (a) */


Reply via email to