this is a follow-up to "use tasks and a task_list to manage
if_detachhooks" and converts the link state hooks to a task_list
with pre-allocated tasks.

it's mostly mechanical, except for carp. each carp interface has a link
state hook it registers on its parent, but each hook then runs against
every carp device on that parent. the diff changes it so the link state
hook is only run for the relevant carp interface.

it also reorders the addition of the carp link state hook till after the
old link state hook is removed.

unless anyone objects i am going to commit this around 10am GMT+10
tomorrow (7th nov).

Index: net/if.c
===================================================================
RCS file: /cvs/src/sys/net/if.c,v
retrieving revision 1.589
diff -u -p -r1.589 if.c
--- net/if.c    6 Nov 2019 03:51:26 -0000       1.589
+++ net/if.c    6 Nov 2019 05:04:03 -0000
@@ -629,9 +629,7 @@ if_attach_common(struct ifnet *ifp)
        ifp->if_addrhooks = malloc(sizeof(*ifp->if_addrhooks),
            M_TEMP, M_WAITOK);
        TAILQ_INIT(ifp->if_addrhooks);
-       ifp->if_linkstatehooks = malloc(sizeof(*ifp->if_linkstatehooks),
-           M_TEMP, M_WAITOK);
-       TAILQ_INIT(ifp->if_linkstatehooks);
+       TAILQ_INIT(&ifp->if_linkstatehooks);
        TAILQ_INIT(&ifp->if_detachhooks);
 
        if (ifp->if_rtrequest == NULL)
@@ -1055,8 +1053,6 @@ if_deactivate(struct ifnet *ifp)
        NET_LOCK();
        TAILQ_FOREACH_SAFE(t, &ifp->if_detachhooks, t_entry, nt)
                (*t->t_func)(t->t_arg);
-
-       KASSERT(TAILQ_EMPTY(&ifp->if_detachhooks));
        NET_UNLOCK();
 }
 
@@ -1148,7 +1144,8 @@ if_detach(struct ifnet *ifp)
        }
 
        free(ifp->if_addrhooks, M_TEMP, sizeof(*ifp->if_addrhooks));
-       free(ifp->if_linkstatehooks, M_TEMP, sizeof(*ifp->if_linkstatehooks));
+       KASSERT(TAILQ_EMPTY(&ifp->if_linkstatehooks));
+       KASSERT(TAILQ_EMPTY(&ifp->if_detachhooks));
 
        for (i = 0; (dp = domains[i]) != NULL; i++) {
                if (dp->dom_ifdetach && ifp->if_afdata[dp->dom_family])
@@ -1646,11 +1643,29 @@ if_linkstate_task(void *xifidx)
 void
 if_linkstate(struct ifnet *ifp)
 {
+       struct task *t, *nt;
+
        NET_ASSERT_LOCKED();
 
        rtm_ifchg(ifp);
        rt_if_track(ifp);
-       dohooks(ifp->if_linkstatehooks, 0);
+
+       TAILQ_FOREACH_SAFE(t, &ifp->if_linkstatehooks, t_entry, nt)
+               (*t->t_func)(t->t_arg);
+}
+
+void
+if_linkstatehook_add(struct ifnet *ifp, struct task *t)
+{
+       NET_ASSERT_LOCKED();
+       TAILQ_INSERT_TAIL(&ifp->if_linkstatehooks, t, t_entry);
+}
+
+void
+if_linkstatehook_del(struct ifnet *ifp, struct task *t)
+{
+       NET_ASSERT_LOCKED();
+       TAILQ_REMOVE(&ifp->if_linkstatehooks, t, t_entry);
 }
 
 /*
Index: net/if_aggr.c
===================================================================
RCS file: /cvs/src/sys/net/if_aggr.c,v
retrieving revision 1.20
diff -u -p -r1.20 if_aggr.c
--- net/if_aggr.c       6 Nov 2019 03:51:26 -0000       1.20
+++ net/if_aggr.c       6 Nov 2019 05:04:03 -0000
@@ -335,7 +335,7 @@ struct aggr_port {
        int (*p_output)(struct ifnet *, struct mbuf *, struct sockaddr *,
            struct rtentry *);
 
-       void                    *p_lcookie;
+       struct task              p_lhook;
        struct task              p_dhook;
 
        struct aggr_softc       *p_aggr;
@@ -1135,8 +1135,8 @@ aggr_add_port(struct aggr_softc *sc, con
                }
        }
 
-       p->p_lcookie = hook_establish(ifp0->if_linkstatehooks, 1,
-           aggr_p_linkch, p);
+       task_set(&p->p_lhook, aggr_p_linkch, p);
+       if_linkstatehook_add(ifp0, &p->p_lhook);
 
        task_set(&p->p_dhook, aggr_p_detach, p);
        if_detachhook_add(ifp0, &p->p_dhook);
@@ -1428,7 +1428,7 @@ aggr_p_dtor(struct aggr_softc *sc, struc
        }
 
        if_detachhook_del(ifp0, &p->p_dhook);
-       hook_disestablish(ifp0->if_linkstatehooks, p->p_lcookie);
+       if_linkstatehook_del(ifp0, &p->p_lhook);
 
        if_put(ifp0);
        free(p, M_DEVBUF, sizeof(*p));
Index: net/if_bpe.c
===================================================================
RCS file: /cvs/src/sys/net/if_bpe.c,v
retrieving revision 1.9
diff -u -p -r1.9 if_bpe.c
--- net/if_bpe.c        6 Nov 2019 03:51:26 -0000       1.9
+++ net/if_bpe.c        6 Nov 2019 05:04:03 -0000
@@ -102,7 +102,7 @@ struct bpe_softc {
        int                     sc_rxhprio;
        uint8_t                 sc_group[ETHER_ADDR_LEN];
 
-       void *                  sc_lh_cookie;
+       struct task             sc_ltask;
        struct task             sc_dtask;
 
        struct bpe_map          sc_bridge_map;
@@ -174,6 +174,7 @@ bpe_clone_create(struct if_clone *ifc, i
        sc->sc_txhprio = IF_HDRPRIO_PACKET;
        sc->sc_rxhprio = IF_HDRPRIO_OUTER;
 
+       task_set(&sc->sc_ltask, bpe_link_hook, sc);
        task_set(&sc->sc_dtask, bpe_detach_hook, sc);
 
        rw_init(&sc->sc_bridge_lock, "bpebr");
@@ -634,8 +635,7 @@ bpe_up(struct bpe_softc *sc)
        }
 
        /* Register callback for physical link state changes */
-       sc->sc_lh_cookie = hook_establish(ifp0->if_linkstatehooks, 1,
-           bpe_link_hook, sc);
+       if_linkstatehook_add(ifp0, &sc->sc_ltask);
 
        /* Register callback if parent wants to unregister */
        if_detachhook_add(ifp0, &sc->sc_dtask);
@@ -676,7 +676,7 @@ bpe_down(struct bpe_softc *sc)
        ifp0 = if_get(sc->sc_key.k_if);
        if (ifp0 != NULL) {
                if_detachhook_del(ifp0, &sc->sc_dtask);
-               hook_disestablish(ifp0->if_linkstatehooks, sc->sc_lh_cookie);
+               if_linkstatehook_del(ifp0, &sc->sc_ltask);
                bpe_multi(sc, ifp0, SIOCDELMULTI);
        }
        if_put(ifp0);
Index: net/if_bridge.h
===================================================================
RCS file: /cvs/src/sys/net/if_bridge.h,v
retrieving revision 1.66
diff -u -p -r1.66 if_bridge.h
--- net/if_bridge.h     6 Nov 2019 03:51:26 -0000       1.66
+++ net/if_bridge.h     6 Nov 2019 05:04:03 -0000
@@ -331,7 +331,7 @@ struct bstp_port {
        LIST_ENTRY(bstp_port)   bp_next;
        struct ifnet            *bp_ifp;        /* parent if */
        struct bstp_state       *bp_bs;
-       void                    *bp_lhcookie;   /* if linkstate hook */
+       struct task             bp_ltask;       /* if linkstate hook */
        u_int8_t                bp_active;
        u_int8_t                bp_protover;
        u_int32_t               bp_flags;
Index: net/if_gre.c
===================================================================
RCS file: /cvs/src/sys/net/if_gre.c,v
retrieving revision 1.153
diff -u -p -r1.153 if_gre.c
--- net/if_gre.c        6 Nov 2019 03:51:26 -0000       1.153
+++ net/if_gre.c        6 Nov 2019 05:04:03 -0000
@@ -429,7 +429,7 @@ struct nvgre_softc {
        struct task              sc_send_task;
 
        void                    *sc_inm;
-       void                    *sc_lhcookie;
+       struct task              sc_ltask;
        struct task              sc_dtask;
 
        struct rwlock            sc_ether_lock;
@@ -792,6 +792,7 @@ nvgre_clone_create(struct if_clone *ifc,
 
        mq_init(&sc->sc_send_list, IFQ_MAXLEN * 2, IPL_SOFTNET);
        task_set(&sc->sc_send_task, nvgre_send, sc);
+       task_set(&sc->sc_ltask, nvgre_link_change, sc);
        task_set(&sc->sc_dtask, nvgre_detach, sc);
 
        rw_init(&sc->sc_ether_lock, "nvgrelk");
@@ -3657,13 +3658,7 @@ nvgre_up(struct nvgre_softc *sc)
                unhandled_af(tunnel->t_af);
        }
 
-       sc->sc_lhcookie = hook_establish(ifp0->if_linkstatehooks, 0,
-           nvgre_link_change, sc);
-       if (sc->sc_lhcookie == NULL) {
-               error = ENOMEM;
-               goto delmulti;
-       }
-
+       if_linkstatehook_add(ifp0, &sc->sc_ltask);
        if_detachhook_add(ifp0, &sc->sc_dtask);
 
        if_put(ifp0);
@@ -3675,19 +3670,6 @@ nvgre_up(struct nvgre_softc *sc)
 
        return (0);
 
-delmulti:
-       switch (tunnel->t_af) {
-       case AF_INET:
-               in_delmulti(inm);
-               break;
-#ifdef INET6
-       case AF_INET6:
-               in6_delmulti(inm);
-               break;
-#endif
-       default:
-               unhandled_af(tunnel->t_af);
-       }
 remove_ucast:
        RBT_REMOVE(nvgre_ucast_tree, &nvgre_ucast_tree, sc);
 remove_mcast:
@@ -3721,7 +3703,7 @@ nvgre_down(struct nvgre_softc *sc)
        ifp0 = if_get(sc->sc_ifp0);
        if (ifp0 != NULL) {
                if_detachhook_del(ifp0, &sc->sc_dtask);
-               hook_disestablish(ifp0->if_linkstatehooks, sc->sc_lhcookie);
+               if_linkstatehook_del(ifp0, &sc->sc_ltask);
        }
        if_put(ifp0);
 
Index: net/if_pfsync.c
===================================================================
RCS file: /cvs/src/sys/net/if_pfsync.c,v
retrieving revision 1.265
diff -u -p -r1.265 if_pfsync.c
--- net/if_pfsync.c     6 Nov 2019 03:51:26 -0000       1.265
+++ net/if_pfsync.c     6 Nov 2019 05:04:03 -0000
@@ -235,7 +235,7 @@ struct pfsync_softc {
 
        TAILQ_HEAD(, tdb)        sc_tdb_q;
 
-       void                    *sc_lhcookie;
+       struct task              sc_ltask;
        struct task              sc_dtask;
 
        struct timeout           sc_tmo;
@@ -321,6 +321,7 @@ pfsync_clone_create(struct if_clone *ifc
            NULL);
        TAILQ_INIT(&sc->sc_upd_req_list);
        TAILQ_INIT(&sc->sc_deferrals);
+       task_set(&sc->sc_ltask, pfsync_syncdev_state, sc);
        task_set(&sc->sc_dtask, pfsync_ifdetach, sc);
        sc->sc_deferred = 0;
 
@@ -379,9 +380,7 @@ pfsync_clone_destroy(struct ifnet *ifp)
                carp_group_demote_adj(&sc->sc_if, -1, "pfsync destroy");
 #endif
        if (sc->sc_sync_if) {
-               hook_disestablish(
-                   sc->sc_sync_if->if_linkstatehooks,
-                   sc->sc_lhcookie);
+               if_linkstatehook_del(sc->sc_sync_if, &sc->sc_ltask);
                if_detachhook_del(sc->sc_sync_if, &sc->sc_dtask);
        }
 
@@ -1347,9 +1346,8 @@ pfsyncioctl(struct ifnet *ifp, u_long cm
 
                if (pfsyncr.pfsyncr_syncdev[0] == 0) {
                        if (sc->sc_sync_if) {
-                               hook_disestablish(
-                                   sc->sc_sync_if->if_linkstatehooks,
-                                   sc->sc_lhcookie);
+                               if_linkstatehook_del(sc->sc_sync_if,
+                                   &sc->sc_ltask);
                                if_detachhook_del(sc->sc_sync_if,
                                    &sc->sc_dtask);
                        }
@@ -1372,9 +1370,7 @@ pfsyncioctl(struct ifnet *ifp, u_long cm
                        pfsync_sendout();
 
                if (sc->sc_sync_if) {
-                       hook_disestablish(
-                           sc->sc_sync_if->if_linkstatehooks,
-                           sc->sc_lhcookie);
+                       if_linkstatehook_del(sc->sc_sync_if, &sc->sc_ltask);
                        if_detachhook_del(sc->sc_sync_if, &sc->sc_dtask);
                }
                sc->sc_sync_if = sifp;
@@ -1418,9 +1414,7 @@ pfsyncioctl(struct ifnet *ifp, u_long cm
                ip->ip_src.s_addr = INADDR_ANY;
                ip->ip_dst.s_addr = sc->sc_sync_peer.s_addr;
 
-               sc->sc_lhcookie =
-                   hook_establish(sc->sc_sync_if->if_linkstatehooks, 1,
-                   pfsync_syncdev_state, sc);
+               if_linkstatehook_add(sc->sc_sync_if, &sc->sc_ltask);
                if_detachhook_add(sc->sc_sync_if, &sc->sc_dtask);
 
                pfsync_request_full_update(sc);
Index: net/if_tpmr.c
===================================================================
RCS file: /cvs/src/sys/net/if_tpmr.c,v
retrieving revision 1.5
diff -u -p -r1.5 if_tpmr.c
--- net/if_tpmr.c       6 Nov 2019 03:51:26 -0000       1.5
+++ net/if_tpmr.c       6 Nov 2019 05:04:03 -0000
@@ -86,7 +86,7 @@ struct tpmr_port {
        int (*p_output)(struct ifnet *, struct mbuf *, struct sockaddr *,
            struct rtentry *);
 
-       void                    *p_lcookie;
+       struct task              p_ltask;
        struct task              p_dtask;
 
        struct tpmr_softc       *p_tpmr;
@@ -563,8 +563,9 @@ tpmr_add_port(struct tpmr_softc *sc, con
        if (error != 0)
                goto free;
 
-       p->p_lcookie = hook_establish(ifp0->if_linkstatehooks, 1,
-           tpmr_p_linkch, p);
+       task_set(&p->p_ltask, tpmr_p_linkch, p);
+       if_linkstatehook_add(ifp0, &p->p_ltask);
+
        task_set(&p->p_dtask, tpmr_p_detach, p);
        if_detachhook_add(ifp0, &p->p_dtask);
 
@@ -725,7 +726,7 @@ tpmr_p_dtor(struct tpmr_softc *sc, struc
        }
 
        if_detachhook_del(ifp0, &p->p_dtask);
-       hook_disestablish(ifp0->if_linkstatehooks, p->p_lcookie);
+       if_linkstatehook_del(ifp0, &p->p_ltask);
 
        smr_barrier();
 
Index: net/if_trunk.c
===================================================================
RCS file: /cvs/src/sys/net/if_trunk.c,v
retrieving revision 1.142
diff -u -p -r1.142 if_trunk.c
--- net/if_trunk.c      6 Nov 2019 03:51:26 -0000       1.142
+++ net/if_trunk.c      6 Nov 2019 05:04:03 -0000
@@ -372,8 +372,8 @@ trunk_port_create(struct trunk_softc *tr
        trunk_ether_cmdmulti(tp, SIOCADDMULTI);
 
        /* Register callback for physical link state changes */
-       tp->lh_cookie = hook_establish(ifp->if_linkstatehooks, 1,
-           trunk_port_state, tp);
+       task_set(&tp->tp_ltask, trunk_port_state, tp);
+       if_linkstatehook_add(ifp, &tp->tp_ltask);
 
        /* Register callback if parent wants to unregister */
        task_set(&tp->tp_dtask, trunk_port_ifdetach, tp);
@@ -436,8 +436,8 @@ trunk_port_destroy(struct trunk_port *tp
        ifp->if_ioctl = tp->tp_ioctl;
        ifp->if_output = tp->tp_output;
 
-       hook_disestablish(ifp->if_linkstatehooks, tp->lh_cookie);
        if_detachhook_del(ifp, &tp->tp_dtask);
+       if_linkstatehook_del(ifp, &tp->tp_dtask);
 
        /* Finally, remove the port from the trunk */
        SLIST_REMOVE(&tr->tr_ports, tp, trunk_port, tp_entries);
Index: net/if_trunk.h
===================================================================
RCS file: /cvs/src/sys/net/if_trunk.h,v
retrieving revision 1.28
diff -u -p -r1.28 if_trunk.h
--- net/if_trunk.h      6 Nov 2019 03:51:26 -0000       1.28
+++ net/if_trunk.h      6 Nov 2019 05:04:03 -0000
@@ -165,7 +165,7 @@ struct trunk_port {
        u_char                          tp_iftype;      /* interface type */
        u_int32_t                       tp_prio;        /* port priority */
        u_int32_t                       tp_flags;       /* port flags */
-       void                            *lh_cookie;     /* if state hook */
+       struct task                     tp_ltask;       /* if state hook */
        struct task                     tp_dtask;       /* if detach hook */
 
        /* Redirected callbacks */
Index: net/if_var.h
===================================================================
RCS file: /cvs/src/sys/net/if_var.h,v
retrieving revision 1.101
diff -u -p -r1.101 if_var.h
--- net/if_var.h        6 Nov 2019 03:51:26 -0000       1.101
+++ net/if_var.h        6 Nov 2019 05:04:03 -0000
@@ -125,7 +125,7 @@ struct ifnet {                              /* and the 
entries */
        TAILQ_HEAD(, ifmaddr) if_maddrlist; /* [N] list of multicast records */
        TAILQ_HEAD(, ifg_list) if_groups; /* [N] list of groups per if */
        struct hook_desc_head *if_addrhooks; /* [I] address change callbacks */
-       struct hook_desc_head *if_linkstatehooks; /* [I] link change callbacks*/
+       struct task_list if_linkstatehooks; /* [I] link change callbacks*/
        struct task_list if_detachhooks; /* [I] detach callbacks */
                                /* [I] check or clean routes (+ or -)'d */
        void    (*if_rtrequest)(struct ifnet *, int, struct rtentry *);
@@ -376,6 +376,8 @@ void        if_ih_remove(struct ifnet *, int (*
 
 void   if_detachhook_add(struct ifnet *, struct task *);
 void   if_detachhook_del(struct ifnet *, struct task *);
+void   if_linkstatehook_add(struct ifnet *, struct task *);
+void   if_linkstatehook_del(struct ifnet *, struct task *);
 
 void   if_rxr_livelocked(struct if_rxring *);
 void   if_rxr_init(struct if_rxring *, u_int, u_int);
Index: net/if_vlan.c
===================================================================
RCS file: /cvs/src/sys/net/if_vlan.c,v
retrieving revision 1.201
diff -u -p -r1.201 if_vlan.c
--- net/if_vlan.c       6 Nov 2019 03:51:26 -0000       1.201
+++ net/if_vlan.c       6 Nov 2019 05:04:03 -0000
@@ -97,7 +97,7 @@ struct vlan_softc {
        SRPL_ENTRY(vlan_softc)   sc_list;
        int                      sc_flags;
        struct refcnt            sc_refcnt;
-       void                    *sc_lh_cookie;
+       struct task              sc_ltask;
        struct task              sc_dtask;
        struct ifih             *sc_ifih;
 };
@@ -192,6 +192,7 @@ vlan_clone_create(struct if_clone *ifc, 
        sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK|M_ZERO);
        sc->sc_dead = 0;
        LIST_INIT(&sc->sc_mc_listhead);
+       task_set(&sc->sc_ltask, vlan_link_hook, sc);
        task_set(&sc->sc_dtask, vlan_ifdetach, sc);
        ifp = &sc->sc_if;
        ifp->if_softc = sc;
@@ -534,8 +535,7 @@ vlan_up(struct vlan_softc *sc)
        rw_exit(&vlan_tagh_lk);
 
        /* Register callback for physical link state changes */
-       sc->sc_lh_cookie = hook_establish(ifp0->if_linkstatehooks, 1,
-           vlan_link_hook, sc);
+       if_linkstatehook_add(ifp0, &sc->sc_ltask);
 
        /* Register callback if parent wants to unregister */
        if_detachhook_add(ifp0, &sc->sc_dtask);
@@ -592,7 +592,7 @@ vlan_down(struct vlan_softc *sc)
                        ifpromisc(ifp0, 0);
                vlan_multi_apply(sc, ifp0, SIOCDELMULTI);
                if_detachhook_del(ifp0, &sc->sc_dtask);
-               hook_disestablish(ifp0->if_linkstatehooks, sc->sc_lh_cookie);
+               if_linkstatehook_del(ifp0, &sc->sc_ltask);
        }
        if_put(ifp0);
 
Index: net/if_vxlan.c
===================================================================
RCS file: /cvs/src/sys/net/if_vxlan.c,v
retrieving revision 1.74
diff -u -p -r1.74 if_vxlan.c
--- net/if_vxlan.c      6 Nov 2019 03:51:26 -0000       1.74
+++ net/if_vxlan.c      6 Nov 2019 05:04:03 -0000
@@ -63,7 +63,7 @@ struct vxlan_softc {
 
        struct ip_moptions       sc_imo;
        void                    *sc_ahcookie;
-       void                    *sc_lhcookie;
+       struct task              sc_ltask;
        struct task              sc_dtask;
 
        struct sockaddr_storage  sc_src;
@@ -138,6 +138,7 @@ vxlan_clone_create(struct if_clone *ifc,
        sc->sc_vnetid = VXLAN_VNI_UNSET;
        sc->sc_txhprio = IFQ_TOS2PRIO(IPTOS_PREC_ROUTINE); /* 0 */
        sc->sc_df = htons(0);
+       task_set(&sc->sc_ltask, vxlan_link_change, sc);
        task_set(&sc->sc_dtask, vxlan_if_change, sc);
        task_set(&sc->sc_sendtask, vxlan_send_dispatch, sc);
 
@@ -219,11 +220,7 @@ vxlan_multicast_cleanup(struct ifnet *if
                        hook_disestablish(mifp->if_addrhooks, sc->sc_ahcookie);
                        sc->sc_ahcookie = NULL;
                }
-               if (sc->sc_lhcookie != NULL) {
-                       hook_disestablish(mifp->if_linkstatehooks,
-                           sc->sc_lhcookie);
-                       sc->sc_lhcookie = NULL;
-               }
+               if_linkstatehook_del(mifp, &sc->sc_ltask);
                if_detachhook_del(mifp, &sc->sc_dtask);
 
                if_put(mifp);
@@ -294,11 +291,10 @@ vxlan_multicast_join(struct ifnet *ifp, 
         * Use interface hooks to track any changes on the interface
         * that is used to send out the tunnel traffic as multicast.
         */
+       if_linkstatehook_add(mifp, &sc->sc_ltask);
        if_detachhook_add(mifp, &sc->sc_dtask);
        if ((sc->sc_ahcookie = hook_establish(mifp->if_addrhooks,
-           0, vxlan_addr_change, sc)) == NULL ||
-           (sc->sc_lhcookie = hook_establish(mifp->if_linkstatehooks,
-           0, vxlan_link_change, sc)) == NULL)
+           0, vxlan_addr_change, sc)) == NULL)
                panic("%s: cannot allocate interface hook",
                    mifp->if_xname);
 
Index: netinet/ip_carp.c
===================================================================
RCS file: /cvs/src/sys/netinet/ip_carp.c,v
retrieving revision 1.339
diff -u -p -r1.339 ip_carp.c
--- netinet/ip_carp.c   6 Nov 2019 03:51:26 -0000       1.339
+++ netinet/ip_carp.c   6 Nov 2019 05:04:03 -0000
@@ -132,7 +132,7 @@ struct carp_softc {
 #define        sc_if           sc_ac.ac_if
 #define        sc_carpdev      sc_ac.ac_if.if_carpdev
        void *ah_cookie;
-       void *lh_cookie;
+       struct task sc_ltask;
        struct task sc_dtask;
        struct ip_moptions sc_imo;
 #ifdef INET6
@@ -808,6 +808,7 @@ carp_clone_create(struct if_clone *ifc, 
                return (ENOMEM);
        }
 
+       task_set(&sc->sc_ltask, carp_carpdev_state, sc);
        task_set(&sc->sc_dtask, carpdetach, sc);
 
        sc->sc_suppress = 0;
@@ -956,7 +957,7 @@ carpdetach(void *arg)
                ifpromisc(ifp0, 0);
        sc->sc_carpdev = NULL;
 
-       hook_disestablish(ifp0->if_linkstatehooks, sc->lh_cookie);
+       if_linkstatehook_del(ifp0, &sc->sc_ltask);
        if_detachhook_del(ifp0, &sc->sc_dtask);
 }
 
@@ -1687,20 +1688,13 @@ carp_set_ifp(struct carp_softc *sc, stru
        if (ifp0->if_type != IFT_ETHER)
                return (EINVAL);
 
-       sc->lh_cookie = hook_establish(ifp0->if_linkstatehooks, 1,
-           carp_carpdev_state, ifp0);
-       if (sc->lh_cookie == NULL)
-               return (ENOMEM);
-
        cif = &ifp0->if_carp;
        if (SRPL_EMPTY_LOCKED(cif)) {
                if ((error = ifpromisc(ifp0, 1)))
-                       goto rm_lh;
+                       return (error);
 
-       } else if (carp_check_dup_vhids(sc, cif, NULL)) {
-               error = EINVAL;
-               goto rm_lh;
-       }
+       } else if (carp_check_dup_vhids(sc, cif, NULL))
+               return (EINVAL);
 
        /* detach from old interface */
        if (sc->sc_carpdev != NULL)
@@ -1708,6 +1702,8 @@ carp_set_ifp(struct carp_softc *sc, stru
 
        /* attach carp interface to physical interface */
        if_detachhook_add(ifp0, &sc->sc_dtask);
+       if_linkstatehook_add(ifp0, &sc->sc_ltask);
+
        sc->sc_carpdev = ifp0;
        sc->sc_if.if_capabilities = ifp0->if_capabilities &
            IFCAP_CSUM_MASK;
@@ -1745,14 +1741,9 @@ carp_set_ifp(struct carp_softc *sc, stru
        /* Change input handler of the physical interface. */
        if_ih_insert(ifp0, carp_input, NULL);
 
-       carp_carpdev_state(ifp0);
+       carp_carpdev_state(sc);
 
        return (0);
-
-rm_lh:
-       hook_disestablish(ifp0->if_linkstatehooks, sc->lh_cookie);
-
-       return (error);
 }
 
 void
@@ -2465,35 +2456,24 @@ carp_group_demote_count(struct carp_soft
 void
 carp_carpdev_state(void *v)
 {
-       struct srpl *cif;
-       struct carp_softc *sc;
-       struct ifnet *ifp0 = v;
-
-       if (ifp0->if_type != IFT_ETHER)
-               return;
-
-       cif = &ifp0->if_carp;
-
-       KERNEL_ASSERT_LOCKED(); /* touching if_carp */
-
-       SRPL_FOREACH_LOCKED(sc, cif, sc_list) {
-               int suppressed = sc->sc_suppress;
+       struct carp_softc *sc = v;
+       struct ifnet *ifp0 = sc->sc_carpdev;
+       int suppressed = sc->sc_suppress;
 
-               if (sc->sc_carpdev->if_link_state == LINK_STATE_DOWN ||
-                   !(sc->sc_carpdev->if_flags & IFF_UP)) {
-                       sc->sc_if.if_flags &= ~IFF_RUNNING;
-                       carp_del_all_timeouts(sc);
-                       carp_set_state_all(sc, INIT);
-                       sc->sc_suppress = 1;
-                       carp_setrun_all(sc, 0);
-                       if (!suppressed)
-                               carp_group_demote_adj(&sc->sc_if, 1, "carpdev");
-               } else if (suppressed) {
-                       carp_set_state_all(sc, INIT);
-                       sc->sc_suppress = 0;
-                       carp_setrun_all(sc, 0);
-                       carp_group_demote_adj(&sc->sc_if, -1, "carpdev");
-               }
+       if (ifp0->if_link_state == LINK_STATE_DOWN ||
+           !(ifp0->if_flags & IFF_UP)) {
+               sc->sc_if.if_flags &= ~IFF_RUNNING;
+               carp_del_all_timeouts(sc);
+               carp_set_state_all(sc, INIT);
+               sc->sc_suppress = 1;
+               carp_setrun_all(sc, 0);
+               if (!suppressed)
+                       carp_group_demote_adj(&sc->sc_if, 1, "carpdev");
+       } else if (suppressed) {
+               carp_set_state_all(sc, INIT);
+               sc->sc_suppress = 0;
+               carp_setrun_all(sc, 0);
+               carp_group_demote_adj(&sc->sc_if, -1, "carpdev");
        }
 }
 

Reply via email to