On Wed, 20 May 2015 12:51:53 +0200
Martin Pieuchot <[email protected]> wrote:

>  
> > just for completeness: LINK_STATE_INVALID is 1, and that's what
> > carp_set_state uses for everything but master and backup. so far so
> > good.
> > 
> > ifp is part of the sc which in turn is malloc'd with M_ZERO in
> > carp_clone_create, so link state will be 0 aka LINK_STATE_UNKNOWN.
> > 
> > however, at the end of carp_clone_create, we call
> > carp_set_state_all(sc, INIT) which should take care of that.
> 
> Sadly it does not, because of:
> 
> 2305:         if (vhe->state == state)
> 2306:                 return;
> 
> I'd extend your diff a little bit to make this vhe->state transition
> less confusing, see below.  Do you confirm this also fixes your issue?
> 

The patch did not apply cleanly to OPENBSD_5_7, I rewrote the patch a
bit:
Index: netinet/ip_carp.c
===================================================================
RCS file: /cvs/src/sys/netinet/ip_carp.c,v
retrieving revision 1.247
diff -u -p -r1.247 ip_carp.c
--- netinet/ip_carp.c   4 Mar 2015 10:59:52 -0000       1.247
+++ netinet/ip_carp.c   20 May 2015 11:53:08 -0000
@@ -709,9 +709,7 @@ carpattach(int n)
 }
 
 int
-carp_clone_create(ifc, unit)
-       struct if_clone *ifc;
-       int unit;
+carp_clone_create(struct if_clone *ifc, int unit)
 {
        struct carp_softc *sc;
        struct ifnet *ifp;
@@ -751,6 +749,7 @@ carp_clone_create(ifc, unit)
        ifp->if_addrlen = ETHER_ADDR_LEN;
        ifp->if_hdrlen = ETHER_HDR_LEN;
        ifp->if_mtu = ETHERMTU;
+       ifp->if_link_state = LINK_STATE_INVALID;
        IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
        IFQ_SET_READY(&ifp->if_snd);
        if_attach(ifp);
@@ -764,7 +763,6 @@ carp_clone_create(ifc, unit)
        /* Hook carp_addr_updated to cope with address and route
changes. */ sc->ah_cookie = hook_establish(sc->sc_if.if_addrhooks, 0,
            carp_addr_updated, sc);
-       carp_set_state_all(sc, INIT);
 
        return (0);
 }
@@ -781,6 +779,7 @@ carp_new_vhost(struct carp_softc *sc, in
        vhe->parent_sc = sc;
        vhe->vhid = vhid;
        vhe->advskew = advskew;
+       vhe->state = INIT;
        timeout_set(&vhe->ad_tmo, carp_send_ad, vhe);
        timeout_set(&vhe->md_tmo, carp_master_down, vhe);
        timeout_set(&vhe->md6_tmo, carp_master_down, vhe);
@@ -2288,8 +2287,12 @@ carp_set_state_all(struct carp_softc *sc
 {
        struct carp_vhost_entry *vhe;
 
-       LIST_FOREACH(vhe, &sc->carp_vhosts, vhost_entries)
+       LIST_FOREACH(vhe, &sc->carp_vhosts, vhost_entries) {
+               if (vhe->state == state)
+                       continue;
+
                carp_set_state(vhe, state);
+       }
 }
 
 void
@@ -2299,8 +2302,8 @@ carp_set_state(struct carp_vhost_entry *
        static const char *carp_states[] = { CARP_STATES };
        int loglevel;
 
-       if (vhe->state == state)
-               return;
+       KASSERT(vhe->state != state);
+
        if (vhe->state == INIT || state == INIT)
                loglevel = LOG_WARNING;
        else

With this patch everything (almost) work. At least as good as my patch
did. OSPFd still does something wrong with the link state of carp
interfaces when starting. Have a look at this:

fw2:/usr/src/sys # ospfctl show int
Interface   Address            State  HelloTimer Linkstate  Uptime    nc  ac
carp7       195.58.98.145/28   DOWN   -          backup     00:00:00   0   0
carp5       192.168.253.1/24   DOWN   -          backup     00:00:00   0   0
carp3       192.168.202.1/24   DOWN   -          backup     00:00:00   0   0
carp2       192.168.254.1/23   DOWN   -          invalid    00:00:00   0   0
carp1       31.15.61.129/26    DOWN   -          invalid    00:00:00   0   0
carp0       92.33.0.202/30     DOWN   -          backup     00:00:00   0   0
bnx0        192.168.200.5/24   OTHER  00:00:00   active     00:13:13   4   2

carp2 is (correctly) invalid, because the cable is plugged.
carp1 is _not_ invalid.  If I restart ospfd after the system has come up it
looks better:
carp1       31.15.61.129/26    DOWN   -          backup     00:00:00   0   0

This happens with random interfaces at start-up.
I believe this may be the cause:
in usr.sbin/ospfd/interface.c, if_act_start():

        if (!((iface->flags & IFF_UP) &&
            LINK_STATE_IS_UP(iface->linkstate)))
                return (0);

This check lack the exception for carp interfaces found in ospfe.c. If
the interface already has been initialized when ospfd starts, it will
not pick that interface up as a carp interface.

/Johan

Reply via email to