if_enc(4): Use new KPI to create enc interface

This driver allows only exactly one instance to be created. Clone
creating additional interfaces, e.g. `ifconfig enc1 create`, will get
error EEXIST which is somewhat confusing.

Convert to new KPI for less confusing error ENOSPC.

MFC after:	1 week
Differential Revision:	https://reviews.freebsd.org/D45758

(cherry picked from commit eacad82f3ad0af7d74968e73ed383fc4531d1924)
This commit is contained in:
Zhenlei Huang 2024-06-27 17:22:37 +08:00
parent 1a8cd08d8a
commit 03f7680517

View file

@ -94,8 +94,9 @@ VNET_DEFINE_STATIC(struct if_clone *, enc_cloner);
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 void enc_add_hhooks(struct enc_softc *);
static void enc_remove_hhooks(struct enc_softc *);
@ -139,11 +140,14 @@ SYSCTL_INT(_net_enc_out, OID_AUTO, ipsec_bpf_mask,
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,31 +155,26 @@ enc_clone_destroy(struct ifnet *ifp)
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 (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);
}
@ -375,10 +374,18 @@ enc_remove_hhooks(struct enc_softc *sc)
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,7 +405,8 @@ vnet_enc_uninit(const void *unused __unused)
{
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);