git: eacad82f3ad0 - main - if_enc(4): Use new KPI to create enc interface

From: Zhenlei Huang <zlei_at_FreeBSD.org>
Date: Sat, 12 Oct 2024 13:38:45 UTC
The branch main has been updated by zlei:

URL: https://cgit.FreeBSD.org/src/commit/?id=eacad82f3ad0af7d74968e73ed383fc4531d1924

commit eacad82f3ad0af7d74968e73ed383fc4531d1924
Author:     Zhenlei Huang <zlei@FreeBSD.org>
AuthorDate: 2024-06-27 09:22:37 +0000
Commit:     Zhenlei Huang <zlei@FreeBSD.org>
CommitDate: 2024-10-12 13:37:53 +0000

    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
---
 sys/net/if_enc.c | 46 +++++++++++++++++++++++++++-------------------
 1 file changed, 27 insertions(+), 19 deletions(-)

diff --git a/sys/net/if_enc.c b/sys/net/if_enc.c
index 3c7ae38324c3..3c3f19661063 100644
--- a/sys/net/if_enc.c
+++ b/sys/net/if_enc.c
@@ -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);