hook_establish can fail, but drivers are inconsistent about checking for that. apparently there's also a requirement that detach hooks are run in opposite order to the one they were established in, but that is also applied inconsistently by drivers.
this replaces if_detachhooks with a task_list, and has users of it allocate an set a struct task to put on it. this means the users of it allocate the task up front as part of their per port or softc structure, so adding the task to the if_detachhooks list cannot fail. to enforce the required ordering, ive added wrappers around the list operations. ive had this as a long standing itch to scratch, but i was forced into action after looking at a report by markus@ about the order of these hook establishment/disestablishments in carp. if you reparent a carp interface, you've established detach hooks on multiple interfaces, but if you need to roll back you can lose one of them. this reorders the ops so you only add the detach hook after you've been put on the new interface, and because adding the detach hook is reliable there's no rollback or unwinding to implement. i would love some testing. ive only kicked a few of the tyres on this one. ok? if people are ok with this, i'll go through and do the same for the link state and address change hooks. Index: net/if.c =================================================================== RCS file: /cvs/src/sys/net/if.c,v retrieving revision 1.588 diff -u -p -r1.588 if.c --- net/if.c 21 Aug 2019 15:32:18 -0000 1.588 +++ net/if.c 4 Nov 2019 22:51:52 -0000 @@ -632,9 +623,7 @@ if_attach_common(struct ifnet *ifp) ifp->if_linkstatehooks = malloc(sizeof(*ifp->if_linkstatehooks), M_TEMP, M_WAITOK); TAILQ_INIT(ifp->if_linkstatehooks); - ifp->if_detachhooks = malloc(sizeof(*ifp->if_detachhooks), - M_TEMP, M_WAITOK); - TAILQ_INIT(ifp->if_detachhooks); + TAILQ_INIT(&ifp->if_detachhooks); if (ifp->if_rtrequest == NULL) ifp->if_rtrequest = if_rtrequest_dummy; @@ -1046,17 +1035,36 @@ if_netisr(void *unused) void if_deactivate(struct ifnet *ifp) { - NET_LOCK(); + struct task *t, *nt; + /* * Call detach hooks from head to tail. To make sure detach * hooks are executed in the reverse order they were added, all * the hooks have to be added to the head! */ - dohooks(ifp->if_detachhooks, HOOK_REMOVE | HOOK_FREE); + 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(); } +void +if_detachhook_add(struct ifnet *ifp, struct task *t) +{ + NET_ASSERT_LOCKED(); + TAILQ_INSERT_HEAD(&ifp->if_detachhooks, t, t_entry); +} + +void +if_detachhook_del(struct ifnet *ifp, struct task *t) +{ + NET_ASSERT_LOCKED(); + TAILQ_REMOVE(&ifp->if_detachhooks, t, t_entry); +} + /* * Detach an interface from everything in the kernel. Also deallocate * private resources. @@ -1132,7 +1140,6 @@ 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)); - free(ifp->if_detachhooks, M_TEMP, sizeof(*ifp->if_detachhooks)); for (i = 0; (dp = domains[i]) != NULL; i++) { if (dp->dom_ifdetach && ifp->if_afdata[dp->dom_family]) Index: net/if_aggr.c =================================================================== RCS file: /cvs/src/sys/net/if_aggr.c,v retrieving revision 1.19 diff -u -p -r1.19 if_aggr.c --- net/if_aggr.c 5 Aug 2019 10:42:51 -0000 1.19 +++ net/if_aggr.c 4 Nov 2019 22:51:52 -0000 @@ -336,7 +336,7 @@ struct aggr_port { struct rtentry *); void *p_lcookie; - void *p_dcookie; + struct task p_dtask; struct aggr_softc *p_aggr; TAILQ_ENTRY(aggr_port) p_entry; @@ -1138,8 +1138,9 @@ aggr_add_port(struct aggr_softc *sc, con p->p_lcookie = hook_establish(ifp0->if_linkstatehooks, 1, aggr_p_linkch, p); - p->p_dcookie = hook_establish(ifp0->if_detachhooks, 0, - aggr_p_detach, p); + + task_set(&p->p_dtask, aggr_p_detach, p); + if_detachhook_add(ifp0, &p->p_dtask); task_set(&p->p_rxm_task, aggr_rx, p); mq_init(&p->p_rxm_mq, 3, IPL_NET); @@ -1427,7 +1428,7 @@ aggr_p_dtor(struct aggr_softc *sc, struc ifp->if_xname, op, ifp0->if_xname); } - hook_disestablish(ifp0->if_detachhooks, p->p_dcookie); + if_detachhook_del(ifp0, &p->p_dtask); hook_disestablish(ifp0->if_linkstatehooks, p->p_lcookie); if_put(ifp0); Index: net/if_bpe.c =================================================================== RCS file: /cvs/src/sys/net/if_bpe.c,v retrieving revision 1.8 diff -u -p -r1.8 if_bpe.c --- net/if_bpe.c 17 Jul 2019 16:46:17 -0000 1.8 +++ net/if_bpe.c 4 Nov 2019 22:51:52 -0000 @@ -103,7 +103,7 @@ struct bpe_softc { uint8_t sc_group[ETHER_ADDR_LEN]; void * sc_lh_cookie; - void * sc_dh_cookie; + struct task sc_dtask; struct bpe_map sc_bridge_map; struct rwlock sc_bridge_lock; @@ -174,6 +174,8 @@ bpe_clone_create(struct if_clone *ifc, i sc->sc_txhprio = IF_HDRPRIO_PACKET; sc->sc_rxhprio = IF_HDRPRIO_OUTER; + task_set(&sc->sc_dtask, bpe_detach_hook, sc); + rw_init(&sc->sc_bridge_lock, "bpebr"); RBT_INIT(bpe_map, &sc->sc_bridge_map); sc->sc_bridge_num = 0; @@ -636,8 +638,7 @@ bpe_up(struct bpe_softc *sc) bpe_link_hook, sc); /* Register callback if parent wants to unregister */ - sc->sc_dh_cookie = hook_establish(ifp0->if_detachhooks, 0, - bpe_detach_hook, sc); + if_detachhook_add(ifp0, &sc->sc_dtask); /* we're running now */ SET(ifp->if_flags, IFF_RUNNING); @@ -674,7 +675,7 @@ bpe_down(struct bpe_softc *sc) ifp0 = if_get(sc->sc_key.k_if); if (ifp0 != NULL) { - hook_disestablish(ifp0->if_detachhooks, sc->sc_dh_cookie); + if_detachhook_del(ifp0, &sc->sc_dtask); hook_disestablish(ifp0->if_linkstatehooks, sc->sc_lh_cookie); bpe_multi(sc, ifp0, SIOCDELMULTI); } Index: net/if_bridge.c =================================================================== RCS file: /cvs/src/sys/net/if_bridge.c,v retrieving revision 1.337 diff -u -p -r1.337 if_bridge.c --- net/if_bridge.c 20 Jul 2019 23:01:51 -0000 1.337 +++ net/if_bridge.c 4 Nov 2019 22:51:52 -0000 @@ -325,8 +325,8 @@ bridge_ioctl(struct ifnet *ifp, u_long c SIMPLEQ_INIT(&bif->bif_brlin); SIMPLEQ_INIT(&bif->bif_brlout); ifs->if_bridgeidx = ifp->if_index; - bif->bif_dhcookie = hook_establish(ifs->if_detachhooks, 0, - bridge_ifdetach, bif); + task_set(&bif->bif_dtask, bridge_ifdetach, bif); + if_detachhook_add(ifs, &bif->bif_dtask); if_ih_insert(bif->ifp, bridge_input, NULL); SMR_SLIST_INSERT_HEAD_LOCKED(&sc->sc_iflist, bif, bif_next); break; @@ -385,8 +385,8 @@ bridge_ioctl(struct ifnet *ifp, u_long c bif->bif_flags = IFBIF_SPAN; SIMPLEQ_INIT(&bif->bif_brlin); SIMPLEQ_INIT(&bif->bif_brlout); - bif->bif_dhcookie = hook_establish(ifs->if_detachhooks, 0, - bridge_spandetach, bif); + task_set(&bif->bif_dtask, bridge_spandetach, bif); + if_detachhook_add(ifs, &bif->bif_dtask); SMR_SLIST_INSERT_HEAD_LOCKED(&sc->sc_spanlist, bif, bif_next); break; case SIOCBRDGDELS: @@ -547,7 +547,7 @@ bridge_ifremove(struct bridge_iflist *bi int error; SMR_SLIST_REMOVE_LOCKED(&sc->sc_iflist, bif, bridge_iflist, bif_next); - hook_disestablish(bif->ifp->if_detachhooks, bif->bif_dhcookie); + if_detachhook_del(bif->ifp, &bif->bif_dtask); if_ih_remove(bif->ifp, bridge_input, NULL); smr_barrier(); @@ -575,7 +575,7 @@ bridge_spanremove(struct bridge_iflist * struct bridge_softc *sc = bif->bridge_sc; SMR_SLIST_REMOVE_LOCKED(&sc->sc_spanlist, bif, bridge_iflist, bif_next); - hook_disestablish(bif->ifp->if_detachhooks, bif->bif_dhcookie); + if_detachhook_del(bif->ifp, &bif->bif_dtask); smr_barrier(); Index: net/if_bridge.h =================================================================== RCS file: /cvs/src/sys/net/if_bridge.h,v retrieving revision 1.65 diff -u -p -r1.65 if_bridge.h --- net/if_bridge.h 12 May 2019 19:53:22 -0000 1.65 +++ net/if_bridge.h 4 Nov 2019 22:51:52 -0000 @@ -425,7 +425,7 @@ struct bridge_iflist { struct ifnet *ifp; /* [I] net interface */ u_int32_t bif_flags; /* member flags */ u_int32_t bif_protected; /* protected domains */ - void *bif_dhcookie; + struct task bif_dtask; }; #define bif_state bif_stp->bp_state Index: net/if_gre.c =================================================================== RCS file: /cvs/src/sys/net/if_gre.c,v retrieving revision 1.152 diff -u -p -r1.152 if_gre.c --- net/if_gre.c 29 Jul 2019 16:28:25 -0000 1.152 +++ net/if_gre.c 4 Nov 2019 22:51:52 -0000 @@ -430,7 +407,7 @@ struct nvgre_softc { void *sc_inm; void *sc_lhcookie; - void *sc_dhcookie; + struct task sc_dtask; struct rwlock sc_ether_lock; struct nvgre_map sc_ether_map; @@ -792,6 +769,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_dtask, nvgre_detach, sc); rw_init(&sc->sc_ether_lock, "nvgrelk"); RBT_INIT(nvgre_map, &sc->sc_ether_map); @@ -3663,12 +3630,7 @@ nvgre_up(struct nvgre_softc *sc) goto delmulti; } - sc->sc_dhcookie = hook_establish(ifp0->if_detachhooks, 0, - nvgre_detach, sc); - if (sc->sc_dhcookie == NULL) { - error = ENOMEM; - goto dislh; - } + if_detachhook_add(ifp0, &sc->sc_dtask); if_put(ifp0); @@ -3679,8 +3641,6 @@ nvgre_up(struct nvgre_softc *sc) return (0); -dislh: - hook_disestablish(ifp0->if_linkstatehooks, sc->sc_lhcookie); delmulti: switch (tunnel->t_af) { case AF_INET: @@ -3726,7 +3686,7 @@ nvgre_down(struct nvgre_softc *sc) ifp0 = if_get(sc->sc_ifp0); if (ifp0 != NULL) { - hook_disestablish(ifp0->if_detachhooks, sc->sc_dhcookie); + if_detachhook_del(ifp0, &sc->sc_dtask); hook_disestablish(ifp0->if_linkstatehooks, sc->sc_lhcookie); } if_put(ifp0); Index: net/if_pfsync.c =================================================================== RCS file: /cvs/src/sys/net/if_pfsync.c,v retrieving revision 1.264 diff -u -p -r1.264 if_pfsync.c --- net/if_pfsync.c 10 Jun 2019 16:32:51 -0000 1.264 +++ net/if_pfsync.c 4 Nov 2019 22:51:52 -0000 @@ -236,7 +236,7 @@ struct pfsync_softc { TAILQ_HEAD(, tdb) sc_tdb_q; void *sc_lhcookie; - void *sc_dhcookie; + 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_dtask, pfsync_ifdetach, sc); sc->sc_deferred = 0; TAILQ_INIT(&sc->sc_tdb_q); @@ -381,8 +382,7 @@ pfsync_clone_destroy(struct ifnet *ifp) hook_disestablish( sc->sc_sync_if->if_linkstatehooks, sc->sc_lhcookie); - hook_disestablish(sc->sc_sync_if->if_detachhooks, - sc->sc_dhcookie); + if_detachhook_del(sc->sc_sync_if, &sc->sc_dtask); } /* XXXSMP breaks atomicity */ @@ -1350,9 +1350,8 @@ pfsyncioctl(struct ifnet *ifp, u_long cm hook_disestablish( sc->sc_sync_if->if_linkstatehooks, sc->sc_lhcookie); - hook_disestablish( - sc->sc_sync_if->if_detachhooks, - sc->sc_dhcookie); + if_detachhook_del(sc->sc_sync_if, + &sc->sc_dtask); } sc->sc_sync_if = NULL; if (imo->imo_num_memberships > 0) { @@ -1376,9 +1375,7 @@ pfsyncioctl(struct ifnet *ifp, u_long cm hook_disestablish( sc->sc_sync_if->if_linkstatehooks, sc->sc_lhcookie); - hook_disestablish( - sc->sc_sync_if->if_detachhooks, - sc->sc_dhcookie); + if_detachhook_del(sc->sc_sync_if, &sc->sc_dtask); } sc->sc_sync_if = sifp; @@ -1424,8 +1421,7 @@ pfsyncioctl(struct ifnet *ifp, u_long cm sc->sc_lhcookie = hook_establish(sc->sc_sync_if->if_linkstatehooks, 1, pfsync_syncdev_state, sc); - sc->sc_dhcookie = hook_establish(sc->sc_sync_if->if_detachhooks, - 0, pfsync_ifdetach, sc); + if_detachhook_add(sc->sc_sync_if, &sc->sc_dtask); pfsync_request_full_update(sc); Index: net/if_switch.c =================================================================== RCS file: /cvs/src/sys/net/if_switch.c,v retrieving revision 1.29 diff -u -p -r1.29 if_switch.c --- net/if_switch.c 30 Sep 2019 01:53:05 -0000 1.29 +++ net/if_switch.c 4 Nov 2019 22:51:52 -0000 @@ -533,8 +533,8 @@ switch_port_add(struct switch_softc *sc, ifs->if_switchport = (caddr_t)swpo; if_ih_insert(ifs, switch_input, NULL); swpo->swpo_port_no = swofp_assign_portno(sc, ifs->if_index); - swpo->swpo_dhcookie = hook_establish(ifs->if_detachhooks, 0, - switch_port_detach, ifs); + task_set(&swpo->swpo_dtask, switch_port_detach, ifs); + if_detachhook_add(ifs, &swpo->swpo_dtask); nanouptime(&swpo->swpo_appended); @@ -601,7 +601,7 @@ switch_port_detach(void *arg) switch_port_unset_local(sc, swpo); ifp->if_switchport = NULL; - hook_disestablish(ifp->if_detachhooks, swpo->swpo_dhcookie); + if_detachhook_del(ifp, &swpo->swpo_dtask); ifpromisc(ifp, 0); if_ih_remove(ifp, switch_input, NULL); TAILQ_REMOVE(&sc->sc_swpo_list, swpo, swpo_list_next); Index: net/if_switch.h =================================================================== RCS file: /cvs/src/sys/net/if_switch.h,v retrieving revision 1.11 diff -u -p -r1.11 if_switch.h --- net/if_switch.h 10 May 2019 15:13:38 -0000 1.11 +++ net/if_switch.h 4 Nov 2019 22:51:52 -0000 @@ -175,7 +175,7 @@ struct switch_port { struct switch_softc *swpo_switch; uint32_t swpo_flags; uint32_t swpo_protected; - void *swpo_dhcookie; + struct task swpo_dtask; void (*swop_bk_start)(struct ifnet *); }; Index: net/if_tpmr.c =================================================================== RCS file: /cvs/src/sys/net/if_tpmr.c,v retrieving revision 1.4 diff -u -p -r1.4 if_tpmr.c --- net/if_tpmr.c 12 Sep 2019 02:02:54 -0000 1.4 +++ net/if_tpmr.c 4 Nov 2019 22:51:52 -0000 @@ -87,7 +87,7 @@ struct tpmr_port { struct rtentry *); void *p_lcookie; - void *p_dcookie; + struct task p_dtask; struct tpmr_softc *p_tpmr; unsigned int p_slot; @@ -565,8 +565,8 @@ tpmr_add_port(struct tpmr_softc *sc, con p->p_lcookie = hook_establish(ifp0->if_linkstatehooks, 1, tpmr_p_linkch, p); - p->p_dcookie = hook_establish(ifp0->if_detachhooks, 0, - tpmr_p_detach, p); + task_set(&p->p_dtask, tpmr_p_detach, p); + if_detachhook_add(ifp0, &p->p_dtask); /* commit */ DPRINTF(sc, "%s %s trunkport: creating port\n", @@ -724,7 +724,7 @@ tpmr_p_dtor(struct tpmr_softc *sc, struc ifp->if_xname, ifp0->if_xname); } - hook_disestablish(ifp0->if_detachhooks, p->p_dcookie); + if_detachhook_del(ifp0, &p->p_dtask); hook_disestablish(ifp0->if_linkstatehooks, p->p_lcookie); smr_barrier(); Index: net/if_trunk.c =================================================================== RCS file: /cvs/src/sys/net/if_trunk.c,v retrieving revision 1.141 diff -u -p -r1.141 if_trunk.c --- net/if_trunk.c 5 Jul 2019 01:24:56 -0000 1.141 +++ net/if_trunk.c 4 Nov 2019 22:51:52 -0000 @@ -376,8 +376,8 @@ trunk_port_create(struct trunk_softc *tr trunk_port_state, tp); /* Register callback if parent wants to unregister */ - tp->dh_cookie = hook_establish(ifp->if_detachhooks, 0, - trunk_port_ifdetach, tp); + task_set(&tp->tp_dtask, trunk_port_ifdetach, tp); + if_detachhook_add(ifp, &tp->tp_dtask); if (tr->tr_port_create != NULL) error = (*tr->tr_port_create)(tp); @@ -437,7 +437,7 @@ trunk_port_destroy(struct trunk_port *tp ifp->if_output = tp->tp_output; hook_disestablish(ifp->if_linkstatehooks, tp->lh_cookie); - hook_disestablish(ifp->if_detachhooks, tp->dh_cookie); + if_detachhook_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.27 diff -u -p -r1.27 if_trunk.h --- net/if_trunk.h 29 Apr 2019 04:26:47 -0000 1.27 +++ net/if_trunk.h 4 Nov 2019 22:51:52 -0000 @@ -166,7 +166,7 @@ struct trunk_port { u_int32_t tp_prio; /* port priority */ u_int32_t tp_flags; /* port flags */ void *lh_cookie; /* if state hook */ - void *dh_cookie; /* if detach hook */ + struct task tp_dtask; /* if detach hook */ /* Redirected callbacks */ int (*tp_ioctl)(struct ifnet *, u_long, caddr_t); Index: net/if_var.h =================================================================== RCS file: /cvs/src/sys/net/if_var.h,v retrieving revision 1.100 diff -u -p -r1.100 if_var.h --- net/if_var.h 26 Jun 2019 09:36:06 -0000 1.100 +++ net/if_var.h 4 Nov 2019 22:51:52 -0000 @@ -126,7 +126,7 @@ struct ifnet { /* and the entries */ 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 hook_desc_head *if_detachhooks; /* [I] detach callbacks */ + struct task_list if_detachhooks; /* [I] detach callbacks */ /* [I] check or clean routes (+ or -)'d */ void (*if_rtrequest)(struct ifnet *, int, struct rtentry *); char if_xname[IFNAMSIZ]; /* [I] external name (name + unit) */ @@ -373,6 +373,9 @@ void if_ih_insert(struct ifnet *, int (* void *), void *); void if_ih_remove(struct ifnet *, int (*)(struct ifnet *, struct mbuf *, void *), void *); + +void if_detachhook_add(struct ifnet *, struct task *); +void if_detachhook_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.200 diff -u -p -r1.200 if_vlan.c --- net/if_vlan.c 4 Nov 2019 04:17:31 -0000 1.200 +++ net/if_vlan.c 4 Nov 2019 22:51:52 -0000 @@ -98,7 +98,7 @@ struct vlan_softc { int sc_flags; struct refcnt sc_refcnt; void *sc_lh_cookie; - void *sc_dh_cookie; + 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_dtask, vlan_ifdetach, sc); ifp = &sc->sc_if; ifp->if_softc = sc; snprintf(ifp->if_xname, sizeof ifp->if_xname, "%s%d", ifc->ifc_name, @@ -537,8 +538,7 @@ vlan_up(struct vlan_softc *sc) vlan_link_hook, sc); /* Register callback if parent wants to unregister */ - sc->sc_dh_cookie = hook_establish(ifp0->if_detachhooks, 0, - vlan_ifdetach, sc); + if_detachhook_add(ifp0, &sc->sc_dtask); /* configure the parent to handle packets for this vlan */ vlan_multi_apply(sc, ifp0, SIOCADDMULTI); @@ -591,7 +591,7 @@ vlan_down(struct vlan_softc *sc) if (ISSET(sc->sc_flags, IFVF_PROMISC)) ifpromisc(ifp0, 0); vlan_multi_apply(sc, ifp0, SIOCDELMULTI); - hook_disestablish(ifp0->if_detachhooks, sc->sc_dh_cookie); + if_detachhook_del(ifp0, &sc->sc_dtask); hook_disestablish(ifp0->if_linkstatehooks, sc->sc_lh_cookie); } if_put(ifp0); Index: net/if_vxlan.c =================================================================== RCS file: /cvs/src/sys/net/if_vxlan.c,v retrieving revision 1.73 diff -u -p -r1.73 if_vxlan.c --- net/if_vxlan.c 10 Jun 2019 16:32:51 -0000 1.73 +++ net/if_vxlan.c 4 Nov 2019 22:51:52 -0000 @@ -64,7 +64,7 @@ struct vxlan_softc { struct ip_moptions sc_imo; void *sc_ahcookie; void *sc_lhcookie; - void *sc_dhcookie; + struct task sc_dtask; struct sockaddr_storage sc_src; struct sockaddr_storage sc_dst; @@ -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_dtask, vxlan_if_change, sc); task_set(&sc->sc_sendtask, vxlan_send_dispatch, sc); ifp = &sc->sc_ac.ac_if; @@ -223,11 +224,7 @@ vxlan_multicast_cleanup(struct ifnet *if sc->sc_lhcookie); sc->sc_lhcookie = NULL; } - if (sc->sc_dhcookie != NULL) { - hook_disestablish(mifp->if_detachhooks, - sc->sc_dhcookie); - sc->sc_dhcookie = NULL; - } + if_detachhook_del(mifp, &sc->sc_dtask); if_put(mifp); } @@ -297,12 +294,11 @@ 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_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 || - (sc->sc_dhcookie = hook_establish(mifp->if_detachhooks, - 0, vxlan_if_change, sc)) == NULL) + 0, vxlan_link_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.338 diff -u -p -r1.338 ip_carp.c --- netinet/ip_carp.c 10 Jun 2019 16:32:51 -0000 1.338 +++ netinet/ip_carp.c 4 Nov 2019 22:51:52 -0000 @@ -133,7 +133,7 @@ struct carp_softc { #define sc_carpdev sc_ac.ac_if.if_carpdev void *ah_cookie; void *lh_cookie; - void *dh_cookie; + struct task sc_dtask; struct ip_moptions sc_imo; #ifdef INET6 struct ip6_moptions sc_im6o; @@ -808,6 +808,8 @@ carp_clone_create(struct if_clone *ifc, return (ENOMEM); } + task_set(&sc->sc_dtask, carpdetach, sc); + sc->sc_suppress = 0; sc->sc_advbase = CARP_DFLTINTV; sc->sc_naddrs = sc->sc_naddrs6 = 0; @@ -955,7 +957,7 @@ carpdetach(void *arg) sc->sc_carpdev = NULL; hook_disestablish(ifp0->if_linkstatehooks, sc->lh_cookie); - hook_disestablish(ifp0->if_detachhooks, sc->dh_cookie); + if_detachhook_del(ifp0, &sc->sc_dtask); } void @@ -1685,17 +1687,10 @@ 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; - } + if (sc->lh_cookie == NULL) + return (ENOMEM); cif = &ifp0->if_carp; if (SRPL_EMPTY_LOCKED(cif)) { @@ -1712,6 +1707,7 @@ carp_set_ifp(struct carp_softc *sc, stru carpdetach(sc); /* attach carp interface to physical interface */ + if_detachhook_add(ifp0, &sc->sc_dtask); sc->sc_carpdev = ifp0; sc->sc_if.if_capabilities = ifp0->if_capabilities & IFCAP_CSUM_MASK; @@ -1755,8 +1751,6 @@ carp_set_ifp(struct carp_softc *sc, stru rm_lh: hook_disestablish(ifp0->if_linkstatehooks, sc->lh_cookie); -rm_dh: - hook_disestablish(ifp0->if_detachhooks, sc->dh_cookie); return (error); }