Module Name: src Committed By: ozaki-r Date: Fri May 19 08:53:51 UTC 2017
Modified Files: src/sys/net: if.c if.h src/sys/netinet: ip_carp.c Log Message: Allow CARP to call the link_state_change handler immediately If the handler is delayed because of the indirection call via softint, some operations are executed in reverse and may cause unexpected behaviors. For example, due to the issue a GARP packet wasn't sent on a transition from the BACKUP state to the MASTER state; this happened because IN_IFF_DETACHED flag wasn't cleared on arpannounce, which had been cleared in the link_state_change handler. This fixes an issue reported by sborrill@ on tech-net: http://mail-index.netbsd.org/tech-net/2017/03/14/msg006283.html To generate a diff of this commit: cvs rdiff -u -r1.392 -r1.393 src/sys/net/if.c cvs rdiff -u -r1.238 -r1.239 src/sys/net/if.h cvs rdiff -u -r1.89 -r1.90 src/sys/netinet/ip_carp.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/net/if.c diff -u src/sys/net/if.c:1.392 src/sys/net/if.c:1.393 --- src/sys/net/if.c:1.392 Thu Apr 6 09:20:07 2017 +++ src/sys/net/if.c Fri May 19 08:53:51 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: if.c,v 1.392 2017/04/06 09:20:07 ozaki-r Exp $ */ +/* $NetBSD: if.c,v 1.393 2017/05/19 08:53:51 ozaki-r Exp $ */ /*- * Copyright (c) 1999, 2000, 2001, 2008 The NetBSD Foundation, Inc. @@ -90,7 +90,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if.c,v 1.392 2017/04/06 09:20:07 ozaki-r Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if.c,v 1.393 2017/05/19 08:53:51 ozaki-r Exp $"); #if defined(_KERNEL_OPT) #include "opt_inet.h" @@ -2247,16 +2247,20 @@ out: /* * Handle interface link state change notifications. - * Must be called at splnet(). */ -static void -if_link_state_change0(struct ifnet *ifp, int link_state) +void +if_link_state_change_softint(struct ifnet *ifp, int link_state) { struct domain *dp; + int s = splnet(); + + KASSERT(!cpu_intr_p()); /* Ensure the change is still valid. */ - if (ifp->if_link_state == link_state) + if (ifp->if_link_state == link_state) { + splx(s); return; + } #ifdef DEBUG log(LOG_DEBUG, "%s: link state %s (was %s)\n", ifp->if_xname, @@ -2301,6 +2305,7 @@ if_link_state_change0(struct ifnet *ifp, if (dp->dom_if_link_state_change != NULL) dp->dom_if_link_state_change(ifp, link_state); } + splx(s); } /* @@ -2321,7 +2326,7 @@ if_link_state_change_si(void *arg) /* Pop a link state change from the queue and process it. */ LQ_POP(ifp->if_link_queue, state); - if_link_state_change0(ifp, state); + if_link_state_change_softint(ifp, state); /* If there is a link state change to come, schedule it. */ if (LQ_ITEM(ifp->if_link_queue, 0) != LINK_STATE_UNSET) Index: src/sys/net/if.h diff -u src/sys/net/if.h:1.238 src/sys/net/if.h:1.239 --- src/sys/net/if.h:1.238 Thu Apr 6 03:54:59 2017 +++ src/sys/net/if.h Fri May 19 08:53:51 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: if.h,v 1.238 2017/04/06 03:54:59 ozaki-r Exp $ */ +/* $NetBSD: if.h,v 1.239 2017/05/19 08:53:51 ozaki-r Exp $ */ /*- * Copyright (c) 1999, 2000, 2001 The NetBSD Foundation, Inc. @@ -956,6 +956,7 @@ void if_purgeaddrs(struct ifnet *, int, void if_detach(struct ifnet *); void if_down(struct ifnet *); void if_link_state_change(struct ifnet *, int); +void if_link_state_change_softint(struct ifnet *, int); void if_up(struct ifnet *); void ifinit(void); void ifinit1(void); Index: src/sys/netinet/ip_carp.c diff -u src/sys/netinet/ip_carp.c:1.89 src/sys/netinet/ip_carp.c:1.90 --- src/sys/netinet/ip_carp.c:1.89 Fri May 12 17:53:54 2017 +++ src/sys/netinet/ip_carp.c Fri May 19 08:53:51 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: ip_carp.c,v 1.89 2017/05/12 17:53:54 ryo Exp $ */ +/* $NetBSD: ip_carp.c,v 1.90 2017/05/19 08:53:51 ozaki-r Exp $ */ /* $OpenBSD: ip_carp.c,v 1.113 2005/11/04 08:11:54 mcbride Exp $ */ /* @@ -33,7 +33,7 @@ #endif #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ip_carp.c,v 1.89 2017/05/12 17:53:54 ryo Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ip_carp.c,v 1.90 2017/05/19 08:53:51 ozaki-r Exp $"); /* * TODO: @@ -2191,7 +2191,7 @@ carp_set_state(struct carp_softc *sc, in link_state = LINK_STATE_UNKNOWN; break; } - if_link_state_change(&sc->sc_if, link_state); + if_link_state_change_softint(&sc->sc_if, link_state); } void