git: 239aebee61b8 - main - domain: give domains a chance to probe for availability

Kyle Evans kevans at FreeBSD.org
Mon Aug 16 06:08:18 UTC 2021


The branch main has been updated by kevans:

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

commit 239aebee61b85d9a050d09a37fce2c2df8f36fc1
Author:     Kyle Evans <kevans at FreeBSD.org>
AuthorDate: 2020-06-26 02:17:47 +0000
Commit:     Kyle Evans <kevans at FreeBSD.org>
CommitDate: 2021-08-16 05:59:56 +0000

    domain: give domains a chance to probe for availability
    
    This gives any given domain a chance to indicate that it's not actually
    supported on the current system. If dom_probe isn't supplied, we assume
    the domain is universally applicable as most of them are. Keeping
    fully-initialized and registered domains around that physically can't
    work on a large majority of FreeBSD deployments is sub-optimal and leads
    to errors that aren't consistent with the reality of why the socket
    can't be created (e.g. ESOCKTNOSUPPORT) because such scenario has to be
    caught upon pru_attach, at which point kicking back the more-appropriate
    EAFNOSUPPORT would seem weird.
    
    The initial consumer of this will be hvsock, which is only available on
    HyperV guests.
    
    Reviewed by:    cem (earlier version), bcr (manpages)
    Differential Revision:  https://reviews.freebsd.org/D25062
---
 share/man/man9/Makefile |  1 +
 share/man/man9/domain.9 | 32 +++++++++++++++++++++++++++++---
 sys/kern/uipc_domain.c  |  9 +++++++++
 sys/sys/domain.h        |  5 +++++
 4 files changed, 44 insertions(+), 3 deletions(-)

diff --git a/share/man/man9/Makefile b/share/man/man9/Makefile
index 47c642319049..d7d26419b042 100644
--- a/share/man/man9/Makefile
+++ b/share/man/man9/Makefile
@@ -1011,6 +1011,7 @@ MLINKS+=dnv.9 dnvlist.9 \
 	dnv.9 dnvlist_take_string.9
 MLINKS+=domain.9 DOMAIN_SET.9 \
 	domain.9 domain_add.9 \
+	domain.9 domain_init.9 \
 	domain.9 pfctlinput.9 \
 	domain.9 pffinddomain.9 \
 	domain.9 pffindproto.9 \
diff --git a/share/man/man9/domain.9 b/share/man/man9/domain.9
index e8f97253a1d4..03e83edfc14b 100644
--- a/share/man/man9/domain.9
+++ b/share/man/man9/domain.9
@@ -31,6 +31,7 @@
 .Os
 .Sh NAME
 .Nm domain_add ,
+.Nm domain_init ,
 .Nm pfctlinput ,
 .Nm pffinddomain ,
 .Nm pffindproto ,
@@ -45,6 +46,8 @@
 .Ft void
 .Fn domain_add "void *data"
 .Ft void
+.Fn domain_init "void *data"
+.Ft void
 .Fn pfctlinput "int cmd" "struct sockaddr *sa"
 .Ft struct domain *
 .Fn pffinddomain "int family"
@@ -65,8 +68,10 @@ and
 struct domain {
 	int	dom_family;		/* AF_xxx */
 	char	*dom_name;
+	int	dom_flags;
 	void	(*dom_init)		/* initialize domain data structures */
 		(void);
+	int	(*dom_probe)(void);	/* check for support (optional) */
 	void	(*dom_destroy)		/* cleanup structures / state */
 		(void);
 	int	(*dom_externalize)	/* externalize access rights */
@@ -143,15 +148,36 @@ is not called directly, instead
 .Fn DOMAIN_SET
 is used.
 .Pp
-If the new domain has defined an initialization routine, it is called by
-.Fn domain_add ;
+If the new domain has defined a probe routine, it is called first in
+.Fn domain_add
+to determine if the domain should be supported on the current system.
+If the probe routine returns a non-0 value, then the domain will not be
+marked as supported.
+Unsupported domains do not proceed with the initialization process and are not
+discoverable by
+.Fn pffinddomain ,
+.Fn pffindtype ,
+or
+.Fn pffindproto .
+.Pp
+.Fn domain_init
+is called after
+.Fn domain_add
+during boot and for each
+.Xr vnet 9 .
+If the new domain has defined an initialization routine, it is called during
+.Fn domain_init ;
 as well, each of the protocols within the domain that have defined an
 initialization routine will have theirs called.
+Note that domain initialization cannot fail at this time.
 .Pp
-Once a domain is added it cannot be unloaded.
+Once a domain is added it cannot be completely unloaded.
 This is because there is
 no reference counting system in place to determine if there are any
 active references from sockets within that domain.
+If the domain defines a
+.Fn dom_destroy
+routine, then it will be invoked during vnet teardown.
 .Pp
 .Fn pffinddomain
 finds a domain by family.
diff --git a/sys/kern/uipc_domain.c b/sys/kern/uipc_domain.c
index 60e30eb1ae00..50d6c0a9d9f8 100644
--- a/sys/kern/uipc_domain.c
+++ b/sys/kern/uipc_domain.c
@@ -172,7 +172,11 @@ domain_init(void *arg)
 {
 	struct domain *dp = arg;
 	struct protosw *pr;
+	int flags;
 
+	flags = atomic_load_acq_int(&dp->dom_flags);
+	if ((flags & DOMF_SUPPORTED) == 0)
+		return;
 	if (dp->dom_init)
 		(*dp->dom_init)();
 	for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
@@ -200,6 +204,8 @@ vnet_domain_uninit(void *arg)
 {
 	struct domain *dp = arg;
 
+	if ((atomic_load_acq_int(&dp->dom_flags) & DOMF_SUPPORTED) == 0)
+		return;
 	if (dp->dom_destroy)
 		(*dp->dom_destroy)();
 }
@@ -216,6 +222,9 @@ domain_add(void *data)
 	struct domain *dp;
 
 	dp = (struct domain *)data;
+	if (dp->dom_probe != NULL && (*dp->dom_probe)() != 0)
+		return;
+	atomic_set_rel_int(&dp->dom_flags, DOMF_SUPPORTED);
 	mtx_lock(&dom_mtx);
 	dp->dom_next = domains;
 	domains = dp;
diff --git a/sys/sys/domain.h b/sys/sys/domain.h
index 3d17879f1ccd..a59f4e230a1d 100644
--- a/sys/sys/domain.h
+++ b/sys/sys/domain.h
@@ -50,8 +50,10 @@ struct	rib_head;
 struct domain {
 	int	dom_family;		/* AF_xxx */
 	char	*dom_name;
+	int	dom_flags;
 	void	(*dom_init)		/* initialize domain data structures */
 		(void);
+	int	(*dom_probe)(void);	/* check for support (optional) */
 	void	(*dom_destroy)		/* cleanup structures / state */
 		(void);
 	int	(*dom_externalize)	/* externalize access rights */
@@ -70,6 +72,9 @@ struct domain {
 					/* af-dependent data on ifnet */
 };
 
+/* dom_flags */
+#define	DOMF_SUPPORTED	0x0001	/* System supports this domain. */
+
 #ifdef _KERNEL
 extern int	domain_init_status;
 extern struct	domain *domains;


More information about the dev-commits-src-all mailing list