Index: share/man/man9/Makefile =================================================================== --- share/man/man9/Makefile +++ share/man/man9/Makefile @@ -1005,6 +1005,7 @@ 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 pfctlinput2.9 \ domain.9 pffinddomain.9 \ Index: share/man/man9/domain.9 =================================================================== --- share/man/man9/domain.9 +++ share/man/man9/domain.9 @@ -26,11 +26,12 @@ .\" .\" $FreeBSD$ .\" -.Dd April 29, 2020 +.Dd October 7, 2020 .Dt DOMAIN 9 .Os .Sh NAME .Nm domain_add , +.Nm domain_init , .Nm pfctlinput , .Nm pfctlinput2 , .Nm pffinddomain , @@ -46,6 +47,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 void .Fn pfctlinput2 "int cmd" "struct sockaddr *sa" "void *ctlparam" @@ -68,8 +71,10 @@ 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 */ @@ -167,15 +172,36 @@ .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. Index: sys/dev/hyperv/hvsock/hv_sock.c =================================================================== --- sys/dev/hyperv/hvsock/hv_sock.c +++ sys/dev/hyperv/hvsock/hv_sock.c @@ -74,6 +74,8 @@ MALLOC_DEFINE(M_HVSOCK, "hyperv_socket", "hyperv socket control structures"); +static int hvs_dom_probe(void); + /* The MTU is 16KB per host side's design */ #define HVSOCK_MTU_SIZE (1024 * 16) #define HVSOCK_SEND_BUF_SZ (PAGE_SIZE - sizeof(struct vmpipe_proto_header)) @@ -124,6 +126,7 @@ static struct domain hv_socket_domain = { .dom_family = AF_HYPERV, .dom_name = "hyperv", + .dom_probe = hvs_dom_probe, .dom_protosw = hv_socket_protosw, .dom_protoswNPROTOSW = &hv_socket_protosw[nitems(hv_socket_protosw)] }; @@ -322,6 +325,16 @@ sx_xunlock(&hvs_trans_socks_sx); } +static int +hvs_dom_probe(void) +{ + + /* Don't even give us a chance to attach on non-HyperV. */ + if (vm_guest != VM_GUEST_HV) + return (ENXIO); + return (0); +} + void hvs_trans_init(void) { @@ -329,9 +342,6 @@ if (!IS_DEFAULT_VNET(curvnet)) return; - if (vm_guest != VM_GUEST_HV) - return; - HVSOCK_DBG(HVSOCK_DBG_VERBOSE, "%s: HyperV Socket hvs_trans_init called\n", __func__); @@ -354,9 +364,6 @@ { struct hvs_pcb *pcb = so2hvspcb(so); - if (vm_guest != VM_GUEST_HV) - return (ESOCKTNOSUPPORT); - HVSOCK_DBG(HVSOCK_DBG_VERBOSE, "%s: HyperV Socket hvs_trans_attach called\n", __func__); @@ -383,9 +390,6 @@ { struct hvs_pcb *pcb; - if (vm_guest != VM_GUEST_HV) - return; - HVSOCK_DBG(HVSOCK_DBG_VERBOSE, "%s: HyperV Socket hvs_trans_detach called\n", __func__); @@ -595,9 +599,6 @@ { struct hvs_pcb *pcb; - if (vm_guest != VM_GUEST_HV) - return (ESOCKTNOSUPPORT); - HVSOCK_DBG(HVSOCK_DBG_VERBOSE, "%s: HyperV Socket hvs_trans_disconnect called\n", __func__); @@ -925,9 +926,6 @@ { struct hvs_pcb *pcb; - if (vm_guest != VM_GUEST_HV) - return; - HVSOCK_DBG(HVSOCK_DBG_VERBOSE, "%s: HyperV Socket hvs_trans_close called\n", __func__); @@ -969,9 +967,6 @@ { struct hvs_pcb *pcb = so2hvspcb(so); - if (vm_guest != VM_GUEST_HV) - return; - HVSOCK_DBG(HVSOCK_DBG_VERBOSE, "%s: HyperV Socket hvs_trans_abort called\n", __func__); Index: sys/kern/uipc_domain.c =================================================================== --- sys/kern/uipc_domain.c +++ sys/kern/uipc_domain.c @@ -172,7 +172,11 @@ { 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 @@ { 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 @@ 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; Index: sys/sys/domain.h =================================================================== --- sys/sys/domain.h +++ sys/sys/domain.h @@ -50,8 +50,10 @@ 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 @@ /* 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;