On 20/05/15(Wed) 07:40, Henning Brauer wrote:
> * Johan Ymerson <[email protected]> [2015-05-19 19:25]:
> > On Tue, 2015-05-19 at 11:16 +0000, Johan Ymerson wrote:
> > > On Tue, 2015-05-19 at 11:24 +0100, Stuart Henderson wrote:
> > > > On 2015/05/19 10:10, Johan Ymerson wrote:
> > > > Yes I understand that, but if carp init was counted in "LINK_STATE_DOWN"
> > > > then the metric would be 65535 which I think would still avoid the
> > > > problem you're seeing, and would involve less special-casing in ospfd.
> > > Yes, that would also resolve the issue, but it is a bit illogical to
> > > announce a network we cannot possibly route traffic to (due to hardware
> > > problems).
> > After some more testing I think we can conclude that this is most
> > definitely a kernel issue.
>
> hmm. there's definately more to it.
Indeed
> 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?
Index: netinet/ip_carp.c
===================================================================
RCS file: /cvs/src/sys/netinet/ip_carp.c,v
retrieving revision 1.256
diff -u -p -r1.256 ip_carp.c
--- netinet/ip_carp.c 15 May 2015 11:53:06 -0000 1.256
+++ netinet/ip_carp.c 20 May 2015 10:48:17 -0000
@@ -708,9 +708,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;
@@ -753,11 +751,11 @@ carp_clone_create(ifc, unit)
ifp->if_sadl->sdl_type = IFT_CARP;
ifp->if_output = carp_output;
ifp->if_priority = IF_CARP_DEFAULT_PRIORITY;
+ ifp->if_link_state = LINK_STATE_INVALID;
/* 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);
}
@@ -774,6 +772,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);
@@ -2276,8 +2275,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
@@ -2287,8 +2290,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