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