Hi Tech,

I have noticed that CARP IP-Balancing is broken, so I am testing and
fixing it.

The first problem came in with this commit:
http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/sys/net/if_ethersubr.c.diff?r1=1.176&r2=1.177
It enforces that outgoing packets use the src mac of the carp interface instead
the mac of its carpdev. That's a good idea for failover carp but it breaks
balancing ip(-stealth), because the same source MAC is seen by multiple
switchports now. That leads to continues MAC flapping at switches.
My attached patch fixes the problem. Thanks Martin's refactoring, we can
enforce the right MAC on a central place in carp_start() now.

A second problem was introduced two weeks ago. Since we always check the
destination MAC address of received unicast packets, not only when in
promiscuous mode, carp balancing ip is always broken, not only when in
promiscuous mode. The new check collides with "Clear mcast if received on a
carp IP balanced address." in carp_input().
My fix in net/if_ethersubr.c is probably the wrong place to fix the problem,
but I don't have a better idea for now. Maybe the fix is ok for now, because we
don't have too much time before tagging 5.9.

Both of my fixes are independent from each other. They can be separately
committed.

Thanks and Regards,

Florian



Index: net/if_ethersubr.c
===================================================================
RCS file: /cvs/src/sys/net/if_ethersubr.c,v
retrieving revision 1.233
diff -u -p -r1.233 if_ethersubr.c
--- net/if_ethersubr.c  22 Jan 2016 17:09:05 -0000      1.233
+++ net/if_ethersubr.c  6 Feb 2016 08:15:44 -0000
@@ -354,7 +354,8 @@ ether_input(struct ifnet *ifp, struct mb
         * This check is required in promiscous mode, and for some hypervisors
         * where the MAC filter is 'best effort' only.
         */
-       if ((m->m_flags & (M_BCAST|M_MCAST)) == 0) {
+       if ((m->m_flags & (M_BCAST|M_MCAST)) == 0 &&
+           ifp->if_type != IFT_CARP) {
                if (memcmp(ac->ac_enaddr, eh->ether_dhost, ETHER_ADDR_LEN)) {
                        m_freem(m);
                        return (1);
Index: netinet/ip_carp.c
===================================================================
RCS file: /cvs/src/sys/netinet/ip_carp.c,v
retrieving revision 1.286
diff -u -p -r1.286 ip_carp.c
--- netinet/ip_carp.c   21 Jan 2016 11:23:48 -0000      1.286
+++ netinet/ip_carp.c   6 Feb 2016 08:15:46 -0000
@@ -2275,9 +2275,15 @@ carp_start(struct ifnet *ifp)
                 * advertisements in 'ip' and 'ip-stealth' balacing
                 * modes.
                 */
-               if (sc->sc_balancing != CARP_BAL_IPSTEALTH &&
-                   sc->sc_balancing != CARP_BAL_IP &&
-                   (sc->cur_vhe && !sc->cur_vhe->vhe_leader)) {
+               if (sc->sc_balancing == CARP_BAL_IP ||
+                   sc->sc_balancing == CARP_BAL_IPSTEALTH) {
+                       struct ether_header *eh;
+                       uint8_t *esrc;
+
+                       eh = mtod(m, struct ether_header *);
+                       esrc = ((struct arpcom*) ifp->if_carpdev)->ac_enaddr;
+                       memcpy(eh->ether_shost, esrc, sizeof(eh->ether_shost));
+               } else if (sc->cur_vhe && !sc->cur_vhe->vhe_leader) {
                        struct ether_header *eh;
                        uint8_t *esrc;
 



Reply via email to