diff --git a/sys/net/if_enc.c b/sys/net/if_enc.c --- a/sys/net/if_enc.c +++ b/sys/net/if_enc.c @@ -94,8 +94,9 @@ static int enc_ioctl(struct ifnet *, u_long, caddr_t); static int enc_output(struct ifnet *, struct mbuf *, const struct sockaddr *, struct route *); -static int enc_clone_create(struct if_clone *, int, caddr_t); -static void enc_clone_destroy(struct ifnet *); +static int enc_clone_create(struct if_clone *, char *, size_t, + struct ifc_data *, struct ifnet **); +static int enc_clone_destroy(struct if_clone *, struct ifnet *, uint32_t); static int enc_add_hhooks(struct enc_softc *); static void enc_remove_hhooks(struct enc_softc *); @@ -139,11 +140,14 @@ CTLFLAG_RW | CTLFLAG_VNET, &VNET_NAME(bpf_mask_out), 0, "IPsec output bpf mask"); -static void -enc_clone_destroy(struct ifnet *ifp) +static int +enc_clone_destroy(struct if_clone *ifc, struct ifnet *ifp, uint32_t flags) { struct enc_softc *sc; + if (ifp->if_dunit == 0 && (flags & IFC_F_FORCE) == 0) + return (EINVAL); + sc = ifp->if_softc; KASSERT(sc == V_enc_sc, ("sc != ifp->if_softc")); @@ -151,35 +155,30 @@ if_detach(ifp); if_free(ifp); free(sc, M_DEVBUF); - V_enc_sc = NULL; + return (0); } static int -enc_clone_create(struct if_clone *ifc, int unit, caddr_t params) +enc_clone_create(struct if_clone *ifc, char *name, size_t len, + struct ifc_data *ifd, struct ifnet **ifpp) { struct ifnet *ifp; struct enc_softc *sc; - sc = malloc(sizeof(struct enc_softc), M_DEVBUF, - M_WAITOK | M_ZERO); + sc = malloc(sizeof(struct enc_softc), M_DEVBUF, M_WAITOK | M_ZERO); ifp = sc->sc_ifp = if_alloc(IFT_ENC); if (ifp == NULL) { free(sc, M_DEVBUF); return (ENOSPC); } - if (V_enc_sc != NULL) { - if_free(ifp); - free(sc, M_DEVBUF); - return (EEXIST); - } - V_enc_sc = sc; - if_initname(ifp, encname, unit); + if_initname(ifp, encname, ifd->unit); ifp->if_mtu = ENCMTU; ifp->if_ioctl = enc_ioctl; ifp->if_output = enc_output; ifp->if_softc = sc; if_attach(ifp); bpfattach(ifp, DLT_ENC, sizeof(struct enchdr)); + *ifpp = ifp; return (0); } @@ -385,10 +384,18 @@ static void vnet_enc_init(const void *unused __unused) { + struct ifnet *ifp; - V_enc_sc = NULL; - V_enc_cloner = if_clone_simple(encname, enc_clone_create, - enc_clone_destroy, 1); + struct if_clone_addreq req = { + .create_f = enc_clone_create, + .destroy_f = enc_clone_destroy, + .flags = IFC_F_AUTOUNIT | IFC_F_LIMITUNIT, + .maxunit = 0, + }; + V_enc_cloner = ifc_attach_cloner(encname, &req); + struct ifc_data ifd = { .unit = 0 }; + ifc_create_ifp(encname, &ifd, &ifp); + V_enc_sc = ifp->if_softc; } VNET_SYSINIT(vnet_enc_init, SI_SUB_PSEUDO, SI_ORDER_ANY, vnet_enc_init, NULL); @@ -398,8 +405,10 @@ { KASSERT(V_enc_sc != NULL, ("%s: V_enc_sc is %p\n", __func__, V_enc_sc)); - if (enc_add_hhooks(V_enc_sc) != 0) - enc_clone_destroy(V_enc_sc->sc_ifp); + if (enc_add_hhooks(V_enc_sc) != 0) { + enc_clone_destroy(NULL, V_enc_sc->sc_ifp, IFC_F_FORCE); + V_enc_sc = NULL; /* XXX vnet_enc_uninit() will assert fail */ + } } VNET_SYSINIT(vnet_enc_init_proto, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY, vnet_enc_init_proto, NULL); @@ -409,7 +418,8 @@ { KASSERT(V_enc_sc != NULL, ("%s: V_enc_sc is %p\n", __func__, V_enc_sc)); - if_clone_detach(V_enc_cloner); + ifc_detach_cloner(V_enc_cloner); + V_enc_sc = NULL; } VNET_SYSUNINIT(vnet_enc_uninit, SI_SUB_INIT_IF, SI_ORDER_ANY, vnet_enc_uninit, NULL);