this makes carp less special by having it register detachhooks.
right now if.c treats it better than it needs to.

the diff shuffles establishment of the link status hook and the new
detachhook to make carp_set_ifp fail if the hooks cannot be allocated.

the following seems to work both before and after the diff:

        ifconfig vether1 create

        ifconfig -g carp carpdemote 20
        ifconfig carp0 create
        ifconfig carp0 carpdev vether1 
        ifconfig carp0 vhid 66
        ifconfig carp0 pass `openssl rand -base64 12`
        ifconfig carp0 advskew 192
        ifconfig carp0 inet alias 100.64.0.1 netmask 255.255.255.0

        ifconfig vether1
        ifconfig carp0

        ifconfig vether1 destroy

        ifconfig carp0

tests?

Index: net/if.c
===================================================================
RCS file: /cvs/src/sys/net/if.c,v
retrieving revision 1.537
diff -u -p -r1.537 if.c
--- net/if.c    10 Jan 2018 23:50:39 -0000      1.537
+++ net/if.c    12 Jan 2018 01:50:44 -0000
@@ -1005,11 +1005,6 @@ if_deactivate(struct ifnet *ifp)
         */
        dohooks(ifp->if_detachhooks, HOOK_REMOVE | HOOK_FREE);
 
-#if NCARP > 0
-       /* Remove the interface from any carp group it is a part of.  */
-       if (ifp->if_type != IFT_CARP && !SRPL_EMPTY_LOCKED(&ifp->if_carp))
-               carp_ifdetach(ifp);
-#endif
        NET_UNLOCK();
 }
 
Index: netinet/ip_carp.c
===================================================================
RCS file: /cvs/src/sys/netinet/ip_carp.c,v
retrieving revision 1.325
diff -u -p -r1.325 ip_carp.c
--- netinet/ip_carp.c   12 Jan 2018 00:36:13 -0000      1.325
+++ netinet/ip_carp.c   12 Jan 2018 01:50:44 -0000
@@ -133,6 +133,7 @@ struct carp_softc {
 #define        sc_carpdev      sc_ac.ac_if.if_carpdev
        void *ah_cookie;
        void *lh_cookie;
+       void *dh_cookie;
        struct ip_moptions sc_imo;
 #ifdef INET6
        struct ip6_moptions sc_im6o;
@@ -215,7 +216,7 @@ int carp_proto_input_if(struct ifnet *, 
 int    carp6_proto_input_if(struct ifnet *, struct mbuf **, int *, int);
 #endif
 void   carpattach(int);
-void   carpdetach(struct carp_softc *);
+void   carpdetach(void *);
 int    carp_prepare_ad(struct mbuf *, struct carp_vhost_entry *,
            struct carp_header *);
 void   carp_send_ad_all(void);
@@ -901,8 +902,9 @@ carp_del_all_timeouts(struct carp_softc 
 }
 
 void
-carpdetach(struct carp_softc *sc)
+carpdetach(void *arg)
 {
+       struct carp_softc *sc = arg;
        struct ifnet *ifp0;
        struct srpl *cif;
 
@@ -929,26 +931,13 @@ carpdetach(struct carp_softc *sc)
        /* Restore previous input handler. */
        if_ih_remove(ifp0, carp_input, NULL);
 
-       if (sc->lh_cookie != NULL)
-               hook_disestablish(ifp0->if_linkstatehooks, sc->lh_cookie);
-
        SRPL_REMOVE_LOCKED(&carp_sc_rc, cif, sc, carp_softc, sc_list);
        if (SRPL_EMPTY_LOCKED(cif))
                ifpromisc(ifp0, 0);
        sc->sc_carpdev = NULL;
-}
-
-/* Detach an interface from the carp. */
-void
-carp_ifdetach(struct ifnet *ifp0)
-{
-       struct carp_softc *sc, *nextsc;
-       struct srpl *cif = &ifp0->if_carp;
 
-       KERNEL_ASSERT_LOCKED(); /* touching if_carp */
-
-       SRPL_FOREACH_SAFE_LOCKED(sc, cif, sc_list, nextsc)
-               carpdetach(sc);
+       hook_disestablish(ifp0->if_linkstatehooks, sc->lh_cookie);
+       hook_disestablish(ifp0->if_detachhooks, sc->dh_cookie);
 }
 
 void
@@ -1697,13 +1686,27 @@ carp_set_ifp(struct carp_softc *sc, stru
        if (ifp0->if_type != IFT_ETHER)
                return (EINVAL);
 
+       sc->dh_cookie = hook_establish(ifp0->if_detachhooks, 0,
+            carpdetach, sc);
+       if (sc->dh_cookie == NULL)
+               return (ENOMEM);
+
+       sc->lh_cookie = hook_establish(ifp0->if_linkstatehooks, 1,
+           carp_carpdev_state, ifp0);
+       if (sc->lh_cookie == NULL) {
+               error = ENOMEM;
+               goto rm_dh;
+       }
+
        cif = &ifp0->if_carp;
        if (SRPL_EMPTY_LOCKED(cif)) {
                if ((error = ifpromisc(ifp0, 1)))
-                       return (error);
+                       goto rm_lh;
 
-       } else if (carp_check_dup_vhids(sc, cif, NULL))
-               return (EINVAL);
+       } else if (carp_check_dup_vhids(sc, cif, NULL)) {
+               error = EINVAL;
+               goto rm_lh;
+       }
 
        /* detach from old interface */
        if (sc->sc_carpdev != NULL)
@@ -1744,15 +1747,19 @@ carp_set_ifp(struct carp_softc *sc, stru
                sc->sc_if.if_flags |= IFF_UP;
        carp_set_enaddr(sc);
 
-       sc->lh_cookie = hook_establish(ifp0->if_linkstatehooks, 1,
-           carp_carpdev_state, ifp0);
-
        /* Change input handler of the physical interface. */
        if_ih_insert(ifp0, carp_input, NULL);
 
        carp_carpdev_state(ifp0);
 
        return (0);
+
+rm_lh:
+       hook_disestablish(ifp0->if_linkstatehooks, sc->lh_cookie);
+rm_dh:
+       hook_disestablish(ifp0->if_detachhooks, sc->dh_cookie);
+
+       return (error);
 }
 
 void
Index: netinet/ip_carp.h
===================================================================
RCS file: /cvs/src/sys/netinet/ip_carp.h,v
retrieving revision 1.45
diff -u -p -r1.45 ip_carp.h
--- netinet/ip_carp.h   10 Jan 2018 23:50:39 -0000      1.45
+++ netinet/ip_carp.h   12 Jan 2018 01:50:44 -0000
@@ -193,7 +193,6 @@ carpstat_inc(enum carpstat_counters c)
        counters_inc(carpcounters, c);
 }
 
-void            carp_ifdetach (struct ifnet *);
 int             carp_proto_input(struct mbuf **, int *, int, int);
 void            carp_carpdev_state(void *);
 void            carp_group_demote_adj(struct ifnet *, int, char *);

Reply via email to