git: 8e45fed3aefd - main - if_stf: enable use in vnet jails

From: Kristof Provost <kp_at_FreeBSD.org>
Date: Tue, 09 Nov 2021 08:41:49 UTC
The branch main has been updated by kp:

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

commit 8e45fed3aefd00ff544efce8fedeba5e099d3d01
Author:     Kristof Provost <kp@FreeBSD.org>
AuthorDate: 2021-11-05 11:01:37 +0000
Commit:     Kristof Provost <kp@FreeBSD.org>
CommitDate: 2021-11-09 08:39:53 +0000

    if_stf: enable use in vnet jails
    
    The cloner must be per-vnet so that cloned interfaces get destroyed when
    the vnet goes away. Otherwise we fail assertions in vnet_if_uninit():
    
            panic: vnet_if_uninit:475 tailq &V_ifnet=0xfffffe01665fe070 not empty
            cpuid = 19
            time = 1636107064
            KDB: stack backtrace:
            db_trace_self_wrapper() at db_trace_self_wrapper+0x2b/frame 0xfffffe015d0cac60
            vpanic() at vpanic+0x187/frame 0xfffffe015d0cacc0
            panic() at panic+0x43/frame 0xfffffe015d0cad20
            vnet_if_uninit() at vnet_if_uninit+0x7b/frame 0xfffffe015d0cad30
            vnet_destroy() at vnet_destroy+0x170/frame 0xfffffe015d0cad60
            prison_deref() at prison_deref+0x9b0/frame 0xfffffe015d0cadd0
            sys_jail_remove() at sys_jail_remove+0x119/frame 0xfffffe015d0cae00
            amd64_syscall() at amd64_syscall+0x12e/frame 0xfffffe015d0caf30
            fast_syscall_common() at fast_syscall_common+0xf8/frame 0xfffffe015d0caf30
            --- syscall (508, FreeBSD ELF64, sys_jail_remove), rip = 0x8011e920a, rsp = 0x7fffffffe788, rbp = 0x7fffffffe810 ---
            KDB: enter: panic
    
    MFC after:      3 weeks
    Sponsored by:   Rubicon Communications, LLC ("Netgate")
    Differential Revision:  https://reviews.freebsd.org/D32849
---
 sys/net/if_stf.c | 25 +++++++++++++++++++++----
 1 file changed, 21 insertions(+), 4 deletions(-)

diff --git a/sys/net/if_stf.c b/sys/net/if_stf.c
index a18cf058a6e2..f80ba96e2f59 100644
--- a/sys/net/if_stf.c
+++ b/sys/net/if_stf.c
@@ -169,7 +169,8 @@ static int stf_ioctl(struct ifnet *, u_long, caddr_t);
 static int stf_clone_match(struct if_clone *, const char *);
 static int stf_clone_create(struct if_clone *, char *, size_t, caddr_t);
 static int stf_clone_destroy(struct if_clone *, struct ifnet *);
-static struct if_clone *stf_cloner;
+VNET_DEFINE_STATIC(struct if_clone *, stf_cloner);
+#define V_stf_cloner	VNET(stf_cloner)
 
 static const struct encap_config ipv4_encap_cfg = {
 	.proto = IPPROTO_IPV6,
@@ -281,17 +282,33 @@ stf_clone_destroy(struct if_clone *ifc, struct ifnet *ifp)
 	return (0);
 }
 
+static void
+vnet_stf_init(const void *unused __unused)
+{
+	V_stf_cloner = if_clone_advanced(stfname, 0, stf_clone_match,
+	    stf_clone_create, stf_clone_destroy);
+}
+VNET_SYSINIT(vnet_stf_init, SI_SUB_PSEUDO, SI_ORDER_ANY, vnet_stf_init, NULL);
+
+static void
+vnet_stf_uninit(const void *unused __unused)
+{
+	if_clone_detach(V_stf_cloner);
+	V_stf_cloner = NULL;
+}
+VNET_SYSUNINIT(vnet_stf_uninit, SI_SUB_PSEUDO, SI_ORDER_ANY, vnet_stf_uninit,
+    NULL);
+
 static int
 stfmodevent(module_t mod, int type, void *data)
 {
 
 	switch (type) {
 	case MOD_LOAD:
-		stf_cloner = if_clone_advanced(stfname, 0, stf_clone_match,
-		    stf_clone_create, stf_clone_destroy);
+		/* Done in vnet_stf_init() */
 		break;
 	case MOD_UNLOAD:
-		if_clone_detach(stf_cloner);
+		/* Done in vnet_stf_uninit() */
 		break;
 	default:
 		return (EOPNOTSUPP);