git: 0d0999fe3137 - stable/14 - if_clone: Allow maxunit to be zero

From: Zhenlei Huang <zlei_at_FreeBSD.org>
Date: Sat, 20 Jul 2024 14:44:28 UTC
The branch stable/14 has been updated by zlei:

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

commit 0d0999fe313779ea51ef4178dff76bb572fdb09f
Author:     Zhenlei Huang <zlei@FreeBSD.org>
AuthorDate: 2024-07-03 13:14:08 +0000
Commit:     Zhenlei Huang <zlei@FreeBSD.org>
CommitDate: 2024-07-20 14:42:59 +0000

    if_clone: Allow maxunit to be zero
    
    Some drivers, e.g. if_enc(4), only allow one instance to be created, but
    the KPI ifc_attach_cloner() treat zero value of maxunit as not limited,
    aka IF_MAXUNIT.
    
    Introduce a new flag IFC_F_LIMITUNIT to indicate that the requested
    maxunit is limited and should be respected.
    
    Consumers should use the new flag if there is an intended limit.
    
    Reviewed by:    glebius
    MFC after:      2 weeks
    Differential Revision:  https://reviews.freebsd.org/D45757
    
    (cherry picked from commit a2cac544a668d2834ed41986aca32b44b9819c89)
---
 sys/net/if_clone.c | 13 +++++++++----
 sys/net/if_clone.h |  5 +++++
 2 files changed, 14 insertions(+), 4 deletions(-)

diff --git a/sys/net/if_clone.c b/sys/net/if_clone.c
index 5345d613f9d6..50ebed285d28 100644
--- a/sys/net/if_clone.c
+++ b/sys/net/if_clone.c
@@ -485,12 +485,13 @@ if_clone_alloc(const char *name, int maxunit)
 	struct if_clone *ifc;
 
 	KASSERT(name != NULL, ("%s: no name\n", __func__));
+	MPASS(maxunit >= 0);
 
 	ifc = malloc(sizeof(struct if_clone), M_CLONE, M_WAITOK | M_ZERO);
 	strncpy(ifc->ifc_name, name, IFCLOSIZ-1);
 	IF_CLONE_LOCK_INIT(ifc);
 	IF_CLONE_ADDREF(ifc);
-	ifc->ifc_maxunit = maxunit ? maxunit : IF_MAXUNIT;
+	ifc->ifc_maxunit = maxunit;
 	ifc->ifc_unrhdr = new_unrhdr(0, ifc->ifc_maxunit, &ifc->ifc_mtx);
 	LIST_INIT(&ifc->ifc_iflist);
 
@@ -523,12 +524,16 @@ if_clone_attach(struct if_clone *ifc)
 struct if_clone *
 ifc_attach_cloner(const char *name, struct if_clone_addreq *req)
 {
+	int maxunit;
+	struct if_clone *ifc;
+
 	if (req->create_f == NULL || req->destroy_f == NULL)
 		return (NULL);
 	if (strnlen(name, IFCLOSIZ) >= (IFCLOSIZ - 1))
 		return (NULL);
 
-	struct if_clone *ifc = if_clone_alloc(name, req->maxunit);
+	maxunit = (req->flags & IFC_F_LIMITUNIT) ? req->maxunit : IF_MAXUNIT;
+	ifc = if_clone_alloc(name, maxunit);
 	ifc->ifc_match = req->match_f != NULL ? req->match_f : ifc_simple_match;
 	ifc->ifc_create = req->create_f;
 	ifc->ifc_destroy = req->destroy_f;
@@ -586,7 +591,7 @@ if_clone_advanced(const char *name, u_int maxunit, ifc_match_t match,
 {
 	struct if_clone *ifc;
 
-	ifc = if_clone_alloc(name, maxunit);
+	ifc = if_clone_alloc(name, maxunit ? maxunit : IF_MAXUNIT);
 	ifc->ifc_match = match;
 	ifc->ifc_create = ifc_advanced_create_wrapper;
 	ifc->ifc_destroy = ifc_advanced_destroy_wrapper;
@@ -631,7 +636,7 @@ if_clone_simple(const char *name, ifcs_create_t create, ifcs_destroy_t destroy,
 	struct if_clone *ifc;
 	u_int unit;
 
-	ifc = if_clone_alloc(name, 0);
+	ifc = if_clone_alloc(name, IF_MAXUNIT);
 	ifc->ifc_match = ifc_simple_match;
 	ifc->ifc_create = ifc_simple_create_wrapper;
 	ifc->ifc_destroy = ifc_simple_destroy_wrapper;
diff --git a/sys/net/if_clone.h b/sys/net/if_clone.h
index d44f7021299c..86aa52c0ed25 100644
--- a/sys/net/if_clone.h
+++ b/sys/net/if_clone.h
@@ -103,6 +103,11 @@ struct if_clone_addreq_v2 {
 #define	IFC_F_SYSSPACE	0x04	/* Cloner callback: params pointer is in kernel memory */
 #define	IFC_F_FORCE	0x08	/* Deletion flag: force interface deletion */
 #define	IFC_F_CREATE	0x10	/* Creation flag: indicate creation request */
+#define	IFC_F_LIMITUNIT	0x20	/* Creation flag: the unit number is limited */
+
+_Static_assert(offsetof(struct if_clone_addreq, destroy_f) ==
+    offsetof(struct if_clone_addreq_v2, destroy_f),
+    "destroy_f in if_clone_addreq and if_clone_addreq_v2 are at different offset");
 
 struct if_clone	*ifc_attach_cloner(const char *name, struct if_clone_addreq *req);
 void ifc_detach_cloner(struct if_clone *ifc);