Index: net/bridgestp.c =================================================================== RCS file: /cvs/src/sys/net/bridgestp.c,v retrieving revision 1.72 diff -u -p -r1.72 bridgestp.c --- net/bridgestp.c 13 May 2019 18:20:13 -0000 1.72 +++ net/bridgestp.c 6 Nov 2019 12:32:47 -0000 @@ -1986,9 +1986,8 @@ bstp_add(struct bstp_state *bs, struct i bstp_update_roles(bs, bp); /* Register callback for physical link state changes */ - if (ifp->if_linkstatehooks != NULL) - bp->bp_lhcookie = hook_establish(ifp->if_linkstatehooks, 1, - bstp_ifstate, ifp); + task_set(&bp->bp_ltask, bstp_ifstate, ifp); + if_linkstatehook_add(ifp, &bp->bp_ltask); return (bp); } @@ -2002,8 +2001,7 @@ bstp_delete(struct bstp_port *bp) if (!bp->bp_active) panic("not a bstp member"); - if (ifp != NULL && ifp->if_linkstatehooks != NULL) - hook_disestablish(ifp->if_linkstatehooks, bp->bp_lhcookie); + if_linkstatehook_del(ifp, &bp->bp_ltask); LIST_REMOVE(bp, bp_next); free(bp, M_DEVBUF, sizeof *bp); 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 12:32:47 -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 12:32:47 -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 12:32:47 -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 12:32:47 -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 12:32:47 -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 12:32:47 -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 12:32:47 -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 12:32:47 -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_ltask); /* 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 12:32:47 -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 12:32:47 -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 12:32:47 -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 12:32:47 -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 12:32:47 -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"); } }