[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

CARP diff, please test



This diff fixes a problem with valid routes getting torn away when a
carp device that is in carpdev mode goes to backup.

Please test this even if you're not affected by the above problem, I'd
like some confirmation that it doesn't break other carp configurations
as well.  Successes to me, failures to the list. 

Index: ip_carp.c
===================================================================
RCS file: /cvs/src/sys/netinet/ip_carp.c,v
retrieving revision 1.102
diff -u -r1.102 ip_carp.c
--- ip_carp.c	5 Mar 2005 13:33:49 -0000	1.102
+++ ip_carp.c	13 Mar 2005 04:12:05 -0000
@@ -116,6 +116,7 @@
 
 	int sc_flags_backup;
 	int sc_suppress;
+	int sc_bow_out;
 
 	int sc_sendad_errors;
 #define CARP_SENDAD_MAX_ERRORS	3
@@ -369,10 +370,6 @@
 				}
 				break;
 			case RTM_DELETE:
-				if (nr_ourif)
-					rtrequest(RTM_DELETE, &sa,
-					    ifa->ifa_addr, ifa->ifa_netmask, 0,
-					    NULL);
 				break;
 			default:
 				break;
@@ -858,9 +855,9 @@
 		goto retry_later;
 	}
 
-	/* bow out if we've lost our UPness or RUNNINGuiness */
-	if ((sc->sc_if.if_flags & (IFF_UP|IFF_RUNNING)) !=
-	    (IFF_UP|IFF_RUNNING)) {
+	/* bow out (the carp interface is going down) */
+	if (sc->sc_bow_out) {
+		sc->sc_bow_out = 0;
 		advbase = 255;
 		advskew = 255;
 	} else {
@@ -1325,13 +1322,13 @@
 	switch (sc->sc_state) {
 	case INIT:
 		if (carp_opts[CARPCTL_PREEMPT] && !carp_suppress_preempt) {
+			carp_set_state(sc, MASTER);
+			carp_setroute(sc, RTM_ADD);
 			carp_send_ad(sc);
 			carp_send_arp(sc);
 #ifdef INET6
 			carp_send_na(sc);
 #endif /* INET6 */
-			carp_set_state(sc, MASTER);
-			carp_setroute(sc, RTM_ADD);
 		} else {
 			carp_set_state(sc, BACKUP);
 			carp_setroute(sc, RTM_DELETE);
@@ -1827,12 +1824,16 @@
 
 	case SIOCSIFFLAGS:
 		if (sc->sc_state != INIT && !(ifr->ifr_flags & IFF_UP)) {
-			sc->sc_if.if_flags &= ~IFF_UP;
 			timeout_del(&sc->sc_ad_tmo);
 			timeout_del(&sc->sc_md_tmo);
 			timeout_del(&sc->sc_md6_tmo);
-			if (sc->sc_state == MASTER)
+			if (sc->sc_state == MASTER) {
+				/* we need the interface up to bow out */
+				sc->sc_if.if_flags |= IFF_UP;
+				sc->sc_bow_out = 1;
 				carp_send_ad(sc);
+			}
+			sc->sc_if.if_flags &= ~IFF_UP;
 			carp_set_state(sc, INIT);
 			carp_setrun(sc, 0);
 		} else if (sc->sc_state == INIT && (ifr->ifr_flags & IFF_UP)) {
@@ -1954,10 +1955,10 @@
 carp_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *sa,
     struct rtentry *rt)
 {
-	struct ifnet *ifp0 = ((struct carp_softc *)ifp->if_softc)->sc_carpdev;
+	struct carp_softc *sc = ((struct carp_softc *)ifp->if_softc);
 
-	if (ifp0 != NULL)
-		return (ifp0->if_output(ifp, m, sa, rt));
+	if (sc->sc_carpdev != NULL && sc->sc_state == MASTER)
+		return (sc->sc_carpdev->if_output(ifp, m, sa, rt));
 	else {
 		m_freem(m);
 		return (EINVAL);



Visit your host, monkey.org