diff -urN sys/i386/conf/CORE sys.CORE/i386/conf/CORE
--- sys/i386/conf/CORE	Wed Dec 31 16:00:00 1969
+++ sys.CORE/i386/conf/CORE	Wed Jan 31 16:02:43 2007
@@ -0,0 +1,182 @@
+machine		i386
+cpu		I586_CPU
+cpu		I686_CPU
+ident		CORE
+maxusers	0
+
+makeoptions	DEBUG=-g		#Build kernel with gdb(1) debug symbols
+options		DDB
+
+options 	INET			#InterNETworking
+options 	INET6			#IPv6 communications protocols
+options 	IPSEC
+options 	IPSEC_ESP
+#options 	IPSEC_DEBUG
+options 	FFS			#Berkeley Fast Filesystem
+options 	FFS_ROOT		#FFS usable as root device [keep this!]
+options 	SOFTUPDATES		#Enable FFS soft updates support
+options 	UFS_DIRHASH		#Improve performance on big directories
+options 	MFS			#Memory Filesystem
+options 	MD_ROOT			#MD is a potential root device
+options 	MSDOSFS			#MSDOS Filesystem
+options 	CD9660			#ISO 9660 Filesystem
+options 	CD9660_ROOT		#CD-ROM usable as root, CD9660 required
+options 	PROCFS			#Process filesystem
+options 	COMPAT_43		#Compatible with BSD 4.3 [KEEP THIS!]
+options 	UCONSOLE		#Allow users to grab the console
+options 	USERCONFIG		#boot -c editor
+options 	VISUAL_USERCONFIG	#visual boot -c editor
+options 	KTRACE			#ktrace(1) support
+options 	SYSVSHM			#SYSV-style shared memory
+options 	SYSVMSG			#SYSV-style message queues
+options 	SYSVSEM			#SYSV-style semaphores
+options 	P1003_1B		#Posix P1003_1B real-time extensions
+options 	_KPOSIX_PRIORITY_SCHEDULING
+options 	ICMP_BANDLIM		#Rate limit bad replies
+options 	KBD_INSTALL_CDEV	# install a CDEV entry in /dev
+
+device		isa
+device		pci
+
+# Floppy drives
+device		fdc0	at isa? port IO_FD1 irq 6 drq 2
+device		fd0	at fdc0 drive 0
+
+# ATA and ATAPI devices
+device		ata0	at isa? port IO_WD1 irq 14
+device		ata1	at isa? port IO_WD2 irq 15
+device		ata
+device		atadisk			# ATA disk drives
+device		atapicd			# ATAPI CDROM drives
+device		atapifd			# ATAPI floppy drives
+device		atapist			# ATAPI tape drives
+options 	ATA_STATIC_ID		#Static device numbering
+
+# SCSI peripherals
+device		scbus		# SCSI bus (required)
+device		da		# Direct Access (disks)
+device		sa		# Sequential Access (tape etc)
+device		cd		# CD
+device		pass		# Passthrough device (direct SCSI access)
+
+# atkbdc0 controls both the keyboard and the PS/2 mouse
+device		atkbdc0	at isa? port IO_KBD
+device		atkbd0	at atkbdc? irq 1 flags 0x1
+device		psm0	at atkbdc? irq 12
+
+device		vga0	at isa?
+
+# syscons is the default console driver, resembling an SCO console
+device		sc0	at isa? flags 0x100
+
+device		agp		# support several AGP chipsets
+
+# Floating point support - do not disable.
+device		npx0	at nexus? port IO_NPX irq 13
+
+# Power management support (see LINT for more options)
+#device		apm0	at nexus? #flags 0x20 # Advanced Power Management
+
+# PCCARD (PCMCIA) support
+device		card
+device		pcic0	at isa? irq 0 port 0x3e0 iomem 0xd0000
+device		pcic1	at isa? irq 0 port 0x3e2 iomem 0xd4000 disable
+
+# Serial (COM) ports
+# jeffa: added debug flag
+device		sio0	at isa? port IO_COM1 flags 0x80 irq 4
+#device		sio0	at isa? port IO_COM1 flags 0x10 irq 4
+device		sio1	at isa? port IO_COM2 irq 3
+
+# PCI Ethernet NICs.
+device		de		# DEC/Intel DC21x4x (``Tulip'')
+device		em		# Intel PRO/1000 adapter Gigabit Ethernet Card (``Wiseman'')
+device		txp		# 3Com 3cR990 (``Typhoon'')
+device		vx		# 3Com 3c590, 3c595 (``Vortex'')
+
+# PCI Ethernet NICs that use the common MII bus controller code.
+# NOTE: Be sure to keep the 'device miibus' line in order to use these NICs!
+device		miibus		# MII bus support
+device		dc		# DEC/Intel 21143 and various workalikes
+device		fxp		# Intel EtherExpress PRO/100B (82557, 82558)
+device		pcn		# AMD Am79C97x PCI 10/100 NICs
+device		rl		# RealTek 8129/8139
+device		sf		# Adaptec AIC-6915 (``Starfire'')
+device		sis		# Silicon Integrated Systems SiS 900/SiS 7016
+device		ste		# Sundance ST201 (D-Link DFE-550TX)
+device		tl		# Texas Instruments ThunderLAN
+device		tx		# SMC EtherPower II (83c170 ``EPIC'')
+device		vr		# VIA Rhine, Rhine II
+device		wb		# Winbond W89C840F
+device		xl		# 3Com 3c90x (``Boomerang'', ``Cyclone'')
+device		bge		# Broadcom BCM570x (``Tigon III'')
+
+# ISA Ethernet NICs.
+# 'device ed' requires 'device miibus'
+device		ed0	at isa? disable port 0x280 irq 10 iomem 0xd8000
+device		ex
+device		ep
+device		fe0	at isa? disable port 0x300
+# Xircom Ethernet
+device		xe
+
+# Wireless
+#device		awi
+device		wi
+device		an
+
+# The probe order of these is presently determined by i386/isa/isa_compat.c.
+device		ie0	at isa? disable port 0x300 irq 10 iomem 0xd0000
+#device		le0	at isa? disable port 0x300 irq 5 iomem 0xd0000
+device		lnc0	at isa? disable port 0x280 irq 10 drq 0
+device		cs0	at isa? disable port 0x300
+device		sn0	at isa? disable port 0x300 irq 10
+
+# Pseudo devices - the number indicates how many units to allocate.
+pseudo-device	loop		# Network loopback
+pseudo-device	ether		# Ethernet support
+pseudo-device	tun		# Packet tunnel.
+pseudo-device	pty		# Pseudo-ttys (telnet etc)
+pseudo-device	md		# Memory "disks"
+pseudo-device	gif
+pseudo-device	gre
+
+# The `bpf' pseudo-device enables the Berkeley Packet Filter.
+# Be aware of the administrative consequences of enabling this!
+pseudo-device	bpf		#Berkeley packet filter
+
+# USB support
+device		uhci		# UHCI PCI->USB interface
+device		ohci		# OHCI PCI->USB interface
+device		usb		# USB Bus (required)
+device		ugen		# Generic
+device		uhid		# "Human Interface Devices"
+device		ukbd		# Keyboard
+device		ulpt		# Printer
+device		umass		# Disks/Mass storage - Requires scbus and da
+device		ums		# Mouse
+# USB Ethernet, requires mii
+device		aue		# ADMtek USB ethernet
+device		cue		# CATC USB ethernet
+device		kue		# Kawasaki LSI USB ethernet
+# USB com devices
+device		ucom
+device		uftdi
+
+# LIMUNES specific options
+options		ROOTDEVNAME=\"cd9660:acd0\"
+options		UNION		# Is this really needed?
+options		EXT2FS		# And this?
+pseudo-device	vn	15	# Vnode driver (turns a file into a device)
+
+options		MROUTING	# Multicast routing
+options		PIM		# Protocol Independent Multicast
+#options		IPFIREWALL	# firewall
+#options		IPFIREWALL_DEFAULT_TO_ACCEPT	# allow everything by default
+#options		IPDIVERT	# divert sockets
+
+options		HZ=1000
+#options		AUTO_EOI_1
+options         CPU_ENABLE_SSE
+options         CPU_FASTER_5X86_FPU
+makeoptions     CONF_CFLAGS=-mpentiumpro
diff -urN sys/kern/kern_vimage.c sys.CORE/kern/kern_vimage.c
--- sys/kern/kern_vimage.c	Wed Jan 31 15:57:04 2007
+++ sys.CORE/kern/kern_vimage.c	Wed Jan 31 16:02:43 2007
@@ -52,9 +52,13 @@
 #include <net/bpf.h>
 #include <net/if_types.h>
 #include <net/if_dl.h>
+#include <net/if_gif.h>
 #include <net/ethernet.h>
 
 #include <netinet/tcp_fsm.h>
+#ifdef IPSEC
+#include <netkey/key.h>
+#endif
 
 /* Arbitrary values */
 #define TCP_SYNCACHE_HASHSIZE           512
@@ -107,6 +111,12 @@
 		{ "mrt6stat", V_NET, v_mrt6stat, sizeof (x_vnet->mrt6stat) },
 		{ "mf6ctable", V_NET, v_mf6ctable, sizeof (x_vnet->mf6ctable) },
 		{ "mif6table", V_NET, v_mif6table, sizeof (x_vnet->mif6table) },
+#ifdef IPSEC
+		{ "ipsecstat", V_NET, v_ipsecstat, sizeof (x_vnet->ipsecstat) },
+#ifdef INET6
+		{ "ipsec6stat", V_NET, v_ipsec6stat, sizeof (x_vnet->ipsec6stat) },
+#endif /* INET6 */
+#endif /* IPSEC */
 		{ NULL, 0, 0 , 0 }
 	};
 
@@ -742,7 +752,17 @@
 		}
 
 	rtable_init((void **)vnet->rt_tables, vnet); 
+#ifdef IPSEC
+	if (vnet != vnet0)
+		key_init(vnet);
+#endif
 	vi_loopattach(vnet);
+	if (vnet != vnet0)
+		gif_init(vnet);
+
+	/*Boeing IDC*/
+	if (vnet != vnet0)
+		gre_init(vnet);
 
 	if (IPFW_LOADED)
 		ip_fw_init_ptr(vnet);
@@ -796,6 +816,15 @@
 
 	free((caddr_t)vnet->ifnet_addrs, M_IFADDR);
 	free((caddr_t)vnet->ifindex2ifnet, M_IFADDR);
+
+	while (!LIST_EMPTY(&vnet->gif_softc_list))
+		gif_clone_destroy(&LIST_FIRST(&vnet->gif_softc_list)->gif_if);
+	rman_fini(vnet->gifunits);	
+
+	/*Boeing IDC*/
+	while (!LIST_EMPTY(&vnet->gre_softc_list))
+		gre_clone_destroy(&LIST_FIRST(&vnet->gre_softc_list)->sc_if);
+	rman_fini(vnet->greunits);	
 
 	/* hopefully, we are finally clear to free the vnet container itself! */
 	LIST_REMOVE(vnet, vnet_le);
diff -urN sys/net/if.c sys.CORE/net/if.c
--- sys/net/if.c	Wed Jan 31 15:57:05 2007
+++ sys.CORE/net/if.c	Wed Jan 31 16:19:58 2007
@@ -276,6 +276,11 @@
 			sdl->sdl_data[--namelen] = 0xff;
 		TAILQ_INSERT_HEAD(&ifp->if_addrhead, ifa, ifa_link);
 	}
+#ifdef MROUTING
+#ifdef PIM
+	vnet->reg_vif_num = -1;	/* XXX means VIFI_INVALID */
+#endif
+#endif	
 
 	/* Announce the interface. */
 	rt_ifannouncemsg(ifp, IFAN_ARRIVAL);
diff -urN sys/net/if_gif.c sys.CORE/net/if_gif.c
--- sys/net/if_gif.c	Wed Jan 31 15:57:05 2007
+++ sys.CORE/net/if_gif.c	Wed Jan 31 16:02:43 2007
@@ -90,7 +90,9 @@
 #define GIF_MAXUNIT	0x7fff	/* ifp->if_unit is only 15 bits */
 
 static MALLOC_DEFINE(M_GIF, "gif", "Generic Tunnel Interface");
+#ifdef MOVED_TO_VNET
 static struct rman gifunits[1];
+#endif /* MOVED_TO_VNET */
 
 int	gif_clone_create __P((struct if_clone *, int *, struct vnet *));
 void	gif_clone_destroy __P((struct ifnet *));
@@ -114,22 +116,26 @@
  */
 #define MAX_GIF_NEST 1
 #endif
+#ifdef MOVED_TO_VNET
 static int max_gif_nesting = MAX_GIF_NEST;
-SYSCTL_INT(_net_link_gif, OID_AUTO, max_nesting, CTLFLAG_RW,
-    &max_gif_nesting, 0, "Max nested tunnels");
+#endif /* MOVED_TO_VNET */
+SYSCTL_V_INT(V_NET, _net_link_gif, OID_AUTO, max_nesting, CTLFLAG_RW,
+    v_max_gif_nesting, 0, "Max nested tunnels");
 
 /*
  * By default, we disallow creation of multiple tunnels between the same
  * pair of addresses.  Some applications require this functionality so
  * we allow control over this check here.
  */
+#ifdef MOVED_TO_VNET
 #ifdef XBONEHACK
 static int parallel_tunnels = 1;
 #else
 static int parallel_tunnels = 0;
 #endif
-SYSCTL_INT(_net_link_gif, OID_AUTO, parallel_tunnels, CTLFLAG_RW,
-    &parallel_tunnels, 0, "Allow parallel tunnels?");
+#endif /* MOVED_TO_VNET */
+SYSCTL_V_INT(V_NET, _net_link_gif, OID_AUTO, parallel_tunnels, CTLFLAG_RW,
+    v_parallel_tunnels, 0, "Allow parallel tunnels?");
 
 int
 gif_clone_create(ifc, unit, vnet)
@@ -140,17 +146,19 @@
 	struct resource *r;
 	struct gif_softc *sc;
 
+	if (vnet == NULL)
+		panic("gif_clone_create: NULL vnet was passed.");
 	if (*unit > GIF_MAXUNIT)
 		return (ENXIO);
 
 	if (*unit < 0) {
-		r = rman_reserve_resource(gifunits, 0, GIF_MAXUNIT, 1,
+		r = rman_reserve_resource(vnet->gifunits, 0, GIF_MAXUNIT, 1,
 		    RF_ALLOCATED | RF_ACTIVE, NULL);
 		if (r == NULL)
 			return (ENOSPC);
 		*unit = rman_get_start(r);
 	} else {
-		r = rman_reserve_resource(gifunits, *unit, *unit, 1,
+		r = rman_reserve_resource(vnet->gifunits, *unit, *unit, 1,
 		    RF_ALLOCATED | RF_ACTIVE, NULL);
 		if (r == NULL)
 			return (EEXIST);
@@ -202,6 +210,8 @@
 	struct gif_softc *sc = ifp->if_softc;
 	struct vnet *vnet = ifp->if_vnet;
 
+	if (vnet == NULL)
+		panic("gif_clone_destroy: NULL vnet from ifp.");
 	gif_delete_tunnel(&sc->gif_if);
 	LIST_REMOVE(sc, gif_list);
 #ifdef INET6
@@ -226,31 +236,61 @@
 	free(sc, M_GIF);
 }
 
+/* Initialize gif vars for a single vnet */
+int
+gif_init(vnet)
+	struct vnet *vnet;
+{
+	int err=0;
+
+	vnet->max_gif_nesting = MAX_GIF_NEST;
+	vnet->parallel_tunnels = 0;
+	vnet->gifunits->rm_type = RMAN_ARRAY;
+	vnet->gifunits->rm_descr = "configurable if_gif units";
+	err = rman_init(vnet->gifunits);
+	if (err != 0)
+		return (err);
+	err = rman_manage_region(vnet->gifunits, 0, GIF_MAXUNIT);
+	if (err != 0) {
+		printf("%s: gifunits: rman_manage_region: Failed %d\n",
+		    GIFNAME, err);
+		rman_fini(vnet->gifunits);
+		return (err);
+	}
+	LIST_INIT(&vnet->gif_softc_list);
+
+	return 0;
+}
+
 static int
 gifmodevent(mod, type, data)
 	module_t mod;
 	int type;
 	void *data;
 {
-	int err;
+	int err=0;
 	struct vnet *vnet;
 
 	switch (type) {
 	case MOD_LOAD:
-		gifunits->rm_type = RMAN_ARRAY;
-		gifunits->rm_descr = "configurable if_gif units";
-		err = rman_init(gifunits);
+		LIST_FOREACH(vnet, &vnet_head, vnet_le)
+		{
+		vnet->max_gif_nesting = MAX_GIF_NEST;
+		vnet->parallel_tunnels = 0;
+		vnet->gifunits->rm_type = RMAN_ARRAY;
+		vnet->gifunits->rm_descr = "configurable if_gif units";
+		err = rman_init(vnet->gifunits);
 		if (err != 0)
 			return (err);
-		err = rman_manage_region(gifunits, 0, GIF_MAXUNIT);
+		err = rman_manage_region(vnet->gifunits, 0, GIF_MAXUNIT);
 		if (err != 0) {
 			printf("%s: gifunits: rman_manage_region: Failed %d\n",
 			    GIFNAME, err);
-			rman_fini(gifunits);
+			rman_fini(vnet->gifunits);
 			return (err);
 		}
-		LIST_FOREACH(vnet, &vnet_head, vnet_le)
-			LIST_INIT(&vnet->gif_softc_list);
+		LIST_INIT(&vnet->gif_softc_list);
+		}
 		if_clone_attach(&gif_cloner);
 
 #ifdef INET6
@@ -261,11 +301,12 @@
 	case MOD_UNLOAD:
 		if_clone_detach(&gif_cloner);
 
-		LIST_FOREACH(vnet, &vnet_head, vnet_le)
+		LIST_FOREACH(vnet, &vnet_head, vnet_le) {
 			while (!LIST_EMPTY(&vnet->gif_softc_list))
 				gif_clone_destroy(&LIST_FIRST(&vnet->gif_softc_list)->gif_if);
+			err = rman_fini(vnet->gifunits);
+		}
 
-		err = rman_fini(gifunits);
 		if (err != 0)
 			return (err);
 #ifdef INET6
@@ -295,6 +336,8 @@
 	struct ip ip;
 	struct gif_softc *sc;
 
+	if (vnet == NULL)
+		panic("gif_encapcheck: NULL vnet was passed.");
 	sc = (struct gif_softc *)arg;
 	if (sc == NULL)
 		return 0;
@@ -358,6 +401,11 @@
 	struct gif_softc *sc = (struct gif_softc*)ifp;
 	int error = 0;
 	static int called = 0;	/* XXX: MUTEX */
+	struct vnet *vnet;
+
+	vnet = ifp->if_vnet;
+	/*if (vnet == NULL)
+		panic("gif_output: cannot find vnet.");*/
 
 	/*
 	 * gif may cause infinite recursion calls when misconfigured.
@@ -366,7 +414,7 @@
 	 *      mutual exclusion of the variable CALLED, especially if we
 	 *      use kernel thread.
 	 */
-	if (++called > max_gif_nesting) {
+	if (++called > vnet->max_gif_nesting) {
 		log(LOG_NOTICE,
 		    "gif_output: recursively called too many times(%d)\n",
 		    called);
@@ -441,13 +489,16 @@
 	int s, isr;
 	struct p_ifqueue *p_ifq = NULL;
 	struct ifqueue *ifq;
-	struct vnet *vnet = m->m_pkthdr.rcvif->if_vnet;
+	struct vnet *vnet;
 
 	if (ifp == NULL) {
 		/* just in case */
 		m_freem(m);
 		return;
 	}
+	vnet = ifp->if_vnet;
+	if (vnet == NULL)
+		panic("gif_input: NULL vnet was passed.");
 
 	m->m_pkthdr.rcvif = ifp;
 	
@@ -779,6 +830,8 @@
 	int error = 0; 
 	struct vnet *vnet = sc->gif_vnet;
 
+	if (vnet == NULL)
+		panic("gif_set_tunnel: NULL vnet from sc->gif_vnet");
 	s = splnet();
 
 	LIST_FOREACH(sc2, &vnet->gif_softc_list, gif_list) {
@@ -796,7 +849,7 @@
 		 * Disallow parallel tunnels unless instructed
 		 * otherwise.
 		 */
-		if (!parallel_tunnels &&
+		if (!vnet->parallel_tunnels &&
 		    bcmp(sc2->gif_pdst, dst, dst->sa_len) == 0 &&
 		    bcmp(sc2->gif_psrc, src, src->sa_len) == 0) {
 			error = EADDRNOTAVAIL;
diff -urN sys/net/if_gif.h sys.CORE/net/if_gif.h
--- sys/net/if_gif.h	Wed Jan 31 15:57:05 2007
+++ sys.CORE/net/if_gif.h	Wed Jan 31 16:02:43 2007
@@ -75,6 +75,7 @@
 #define	GIF_MTU_MAX	(8192)	/* Maximum MTU */
 
 /* Prototypes */
+int gif_init(struct vnet *);
 void gifattach0 __P((struct gif_softc *));
 void gif_input __P((struct mbuf *, int, struct ifnet *));
 int gif_output __P((struct ifnet *, struct mbuf *,
diff -urN sys/net/if_gre.c sys.CORE/net/if_gre.c
--- sys/net/if_gre.c	Wed Jan 31 15:57:05 2007
+++ sys.CORE/net/if_gre.c	Wed Jan 31 16:02:43 2007
@@ -97,10 +97,14 @@
 #define GRE_MAXUNIT 0x7fff
 
 static MALLOC_DEFINE(M_GRE, GRENAME, "Generic Routing Encapsulation");
+#ifdef MOVED_TO_VNET
 static struct rman greunits[1];
+#endif /* MOVED_TO_VNET */
 
-static int	gre_clone_create(struct if_clone *, int *, struct vnet *);
-static void	gre_clone_destroy(struct ifnet *);
+/*Boeing IDC static int	gre_clone_create(struct if_clone *, int *, struct vnet *);*/
+/*Boeing IDC static void	gre_clone_destroy(struct ifnet *);*/
+int	gre_clone_create __P((struct if_clone *, int *, struct vnet *));
+void	gre_clone_destroy __P((struct ifnet *));
 static int	gre_ioctl(struct ifnet *, u_long, caddr_t);
 static int	gre_output(struct ifnet *, struct mbuf *, struct sockaddr *,
 		    struct rtentry *rt);
@@ -144,9 +148,11 @@
  */
 #define MAX_GRE_NEST 1
 #endif
+#ifdef MOVED_TO_VNET
 static int max_gre_nesting = MAX_GRE_NEST;
-SYSCTL_INT(_net_link_gre, OID_AUTO, max_nesting, CTLFLAG_RW,
-    &max_gre_nesting, 0, "Max nested tunnels");
+#endif /* MOVED_TO_VNET */
+SYSCTL_V_INT(V_NET, _net_link_gre, OID_AUTO, max_nesting, CTLFLAG_RW,
+    v_max_gre_nesting, 0, "Max nested tunnels");
 
 /* ARGSUSED */
 static void
@@ -167,17 +173,20 @@
 	struct resource *r;
 	struct gre_softc *sc;
 
+	if (vnet == NULL)
+		panic("gre_clone_create: NULL vnet was passed.");
+
 	if (*unit > GRE_MAXUNIT)
 		return (ENXIO);
 
 	if (*unit < 0) {
-		r = rman_reserve_resource(greunits, 0, GRE_MAXUNIT, 1,
+		r = rman_reserve_resource(vnet->greunits, 0, GRE_MAXUNIT, 1,
 		    RF_ALLOCATED | RF_ACTIVE, NULL);
 		if (r == NULL)
 			return (ENOSPC);
 		*unit = rman_get_start(r);
 	} else {
-		r = rman_reserve_resource(greunits, *unit, *unit, 1,
+		r = rman_reserve_resource(vnet->greunits, *unit, *unit, 1,
 		    RF_ALLOCATED | RF_ACTIVE, NULL);
 		if (r == NULL)
 			return (EEXIST);
@@ -211,12 +220,16 @@
 	return (0);
 }
 
-static void
+/*static*/
+void
 gre_clone_destroy(ifp)
 	struct ifnet *ifp;
 {
 	int err;
 	struct gre_softc *sc = ifp->if_softc;
+	/*Boeing IDC copied from if_gif.c*/
+	if (sc->g_vnet == NULL)
+		panic("gre_clone_destroy: NULL vnet from ifp.");
 
 #ifdef INET
 	if (sc->encap != NULL)
@@ -232,6 +245,37 @@
 	free(sc, M_GRE);
 }
 
+
+/*Boeing IDC*/
+
+/* Initialize gif vars for a single vnet */
+int
+gre_init(vnet)
+	struct vnet *vnet;
+{
+	int err=0;
+
+	vnet->max_gre_nesting = MAX_GRE_NEST;
+	vnet->parallel_tunnels = 0;
+	vnet->greunits->rm_type = RMAN_ARRAY;
+	vnet->gifunits->rm_descr = "configurable if_gre units";
+	err = rman_init(vnet->greunits);
+	if (err != 0)
+		return (err);
+	err = rman_manage_region(vnet->greunits, 0, GRE_MAXUNIT);
+	if (err != 0) {
+		printf("%s: greunits: rman_manage_region: Failed %d\n",
+		    GRENAME, err);
+		rman_fini(vnet->greunits);
+		return (err);
+	}
+	LIST_INIT(&vnet->gre_softc_list);
+	return 0;
+}
+
+
+
+
 /*
  * The output routine. Takes a packet and encapsulates it in the protocol
  * given by sc->g_proto. See also RFC 1701 and RFC 2004
@@ -247,12 +291,14 @@
 	u_char osrc;
 	u_short etype = 0;
 	struct mobile_h mob_h;
+	struct vnet *vnet;
 
+	vnet = ifp->if_vnet;
 	/*
 	 * gre may cause infinite recursion calls when misconfigured.
 	 * We'll prevent this by introducing upper limit.
 	 */
-	if (++(sc->called) > max_gre_nesting) {
+	if (++(sc->called) > vnet->max_gre_nesting) {
 		printf("%s: gre_output: recursively called too many "
 		       "times(%d)\n", if_name(&sc->sc_if), sc->called);
 		m_freem(m);
@@ -780,31 +826,33 @@
 
 	switch (type) {
 	case MOD_LOAD:
-		greunits->rm_type = RMAN_ARRAY;
-		greunits->rm_descr = "configurable if_gre units";
-		err = rman_init(greunits);
+		LIST_FOREACH(vnet, &vnet_head, vnet_le)
+		{
+		vnet->max_gre_nesting = MAX_GRE_NEST;
+		vnet->greunits->rm_type = RMAN_ARRAY;
+		vnet->greunits->rm_descr = "configurable if_gre units";
+		err = rman_init(vnet->greunits);
 		if (err != 0)
 			return (err);
-		err = rman_manage_region(greunits, 0, GRE_MAXUNIT);
+		err = rman_manage_region(vnet->greunits, 0, GRE_MAXUNIT);
 		if (err != 0) {
-			printf("%s: greunits: rman_manage_region: Failed %d\n",
-			    GRENAME, err);
-			rman_fini(greunits);
-			return (err);
+		  printf("%s: greunits: rman_manage_region: Failed %d\n",
+			 GRENAME, err);
+		  rman_fini(vnet->greunits);
+		  return (err);
+		}
+		greattach(vnet);
 		}
-	
-		LIST_FOREACH(vnet, &vnet_head, vnet_le)
-			greattach(vnet);
-	
 		break;
 	case MOD_UNLOAD:
 		if_clone_detach(&gre_cloner);
 
-		LIST_FOREACH(vnet, &vnet_head, vnet_le)
+		err = 0;
+		LIST_FOREACH(vnet, &vnet_head, vnet_le) {
 			while (!LIST_EMPTY(&vnet->gre_softc_list))
 				gre_clone_destroy(&LIST_FIRST(&vnet->gre_softc_list)->sc_if);
-
-		err = rman_fini(greunits);
+			err += rman_fini(vnet->greunits);
+		}
 		if (err != 0)
 			return (err);
 
diff -urN sys/net/if_gre.h sys.CORE/net/if_gre.h
--- sys/net/if_gre.h	Wed Jan 31 15:57:05 2007
+++ sys.CORE/net/if_gre.h	Wed Jan 31 16:02:43 2007
@@ -172,4 +172,7 @@
 u_short	gre_in_cksum(u_short *p, u_int len);
 #endif /* _KERNEL */
 
+/* Prototypes */
+int gre_init(struct vnet *);
+
 #endif
diff -urN sys/net/vnet.h sys.CORE/net/vnet.h
--- sys/net/vnet.h	Wed Jan 31 15:57:05 2007
+++ sys.CORE/net/vnet.h	Wed Jan 31 16:02:43 2007
@@ -83,6 +83,15 @@
 #include <netipx/ipx_if.h>
 #include <netipx/ipx_pcb.h>
 
+/* IPsec support */
+#include <netinet6/ipsec.h>
+#include <netkey/keydb.h>
+#include <netkey/key.h>
+#include <netkey/keysock.h>
+/* gif support */
+#include <machine/bus.h>
+#include <sys/rman.h>
+
 #ifdef _KERNEL
 
 int	vi_if_move(struct vi_req *, struct ifnet *, struct vimage *);
@@ -131,6 +140,7 @@
 
 TAILQ_HEAD(dadq_head, dadq);
 
+/**/
 
 struct vnet {
 	LIST_ENTRY(vnet) vnet_le;	/* linked list of all vnets */
@@ -172,7 +182,8 @@
 	struct  ifnet loif;		/* from net/if_loop.c */
 	struct  ifnet vipa;		/* from net/if_loop.c */
 
-	struct	gre_softc_head gre_softc_list;
+  /*Boeing IDC struct	gre_softc_head gre_softc_list;*/
+	LIST_HEAD(, gre_softc) gre_softc_list;
 	LIST_HEAD(, gif_softc) gif_softc_list;
 
 /* NETINET */
@@ -370,6 +381,8 @@
 	struct	udpstat udpstat;	/* from udp_usrreq.c */
 	struct	icmpstat icmpstat;	/* from ip_icmp.c */
 	struct	igmpstat igmpstat;	/* from igmp.c */
+	struct  pfkeystat pfkeystat;	/* from keysock.c */
+	struct  _keystat { u_long getspi_count; } keystat;
 
 	u_int	rsvpdebug;		/* from ip_mroute.c */
 	u_int	mrtdebug;
@@ -571,6 +584,67 @@
 
 	struct	ip_fib_heap_entry ip_fib_heap[33];
 	int	ip_fib_heap_index;
+
+/* gif tunneling interface stuff */
+	/*
+	 * from net/if_gif.c
+	 */
+	 struct rman gifunits[1];
+	 int max_gif_nesting;
+	 int parallel_tunnels;
+	 /*
+	  * from net/if_gre.c
+	  */
+	struct rman greunits[1];
+	int max_gre_nesting;
+/* IPsec stuff */
+/* Do not use #ifdef IPSEC here, or problems will occur! */
+	/* 
+	 * from netkey/key.c 
+	 */
+	u_int key_spi_trycnt;
+	u_int32_t key_spi_minval;
+	u_int32_t key_spi_maxval;
+	u_int32_t policy_id;
+	u_int key_int_random;	/*interval to initialize randseed,1(m)*/
+	u_int key_larval_lifetime; /* interval to expire acquiring, 30(s)*/
+	int key_blockacq_count;	/* counter for blocking SADB_ACQUIRE.*/
+	int key_blockacq_lifetime; /* lifetime for blocking SADB_ACQUIRE.*/
+	int key_preferred_oldsa; /* preferred old sa rather than new sa.*/
+	u_int32_t acq_seq;
+	int key_tick_init_random;
+	LIST_HEAD(_sptree, secpolicy) sptree[IPSEC_DIR_MAX];	/* SPD */
+	LIST_HEAD(_sahtree, secashead) sahtree;			/* SAD */
+	LIST_HEAD(_regtree, secreg) regtree[SADB_SATYPE_MAX + 1]; /* regd list*/
+	LIST_HEAD(_acqtree, secacq) acqtree;		/* acquiring list */
+	LIST_HEAD(_spacqtree, secspacq) spacqtree;	/* SP acquiring list */
+	struct key_cb key_cb;
+
+	/*
+	 * from netinet6/ipsec.c
+	 */
+ 	/* int ipsec_debug;  stays in ipsec.c to avoid unnecessary passing
+	                     of vnet in simple functions that are printing */
+	struct ipsecstat ipsecstat;
+	int ip4_ah_cleartos;
+	int ip4_ah_offsetmask; /* maybe IP_DF? */
+	int ip4_ipsec_dfbit; /* DF bit on encap. 0: clear 1: set 2: copy */
+	int ip4_esp_trans_deflev;
+	int ip4_esp_net_deflev;
+	int ip4_ah_trans_deflev;
+	int ip4_ah_net_deflev;
+	struct secpolicy ip4_def_policy;
+	int ip4_ipsec_ecn; 	/* ECN ignore(-1)/forbidden(0)/allowed(1) */
+	int ip4_esp_randpad;
+	struct ipsecstat ipsec6stat;
+	int ip6_esp_trans_deflev;
+	int ip6_esp_net_deflev;
+	int ip6_ah_trans_deflev;
+	int ip6_ah_net_deflev;
+	struct secpolicy ip6_def_policy;
+	int ip6_ipsec_ecn;	/* ECN ignore(-1)/forbidden(0)/allowed(1) */
+	int ip6_esp_randpad;
+	
 };
 
 /*
@@ -827,7 +901,41 @@
 #define	v_rtq_reallyold6	offsetof(struct vnet, rtq_reallyold6)
 #define	v_rtq_minreallyold6	offsetof(struct vnet, rtq_minreallyold6)
 #define	v_rtq_toomany6		offsetof(struct vnet, rtq_toomany6)
-
+#define v_max_gif_nesting	offsetof(struct vnet, max_gif_nesting)
+#define v_parallel_tunnels	offsetof(struct vnet, parallel_tunnels)
+#define v_max_gre_nesting	offsetof(struct vnet, max_gre_nesting)
+#define v_key_debug_level	offsetof(struct vnet, key_debug_level)
+#define v_key_spi_trycnt	offsetof(struct vnet, key_spi_trycnt)
+#define v_key_spi_minval	offsetof(struct vnet, key_spi_minval)
+#define v_key_spi_maxval	offsetof(struct vnet, key_spi_maxval)
+#define v_policy_id		offsetof(struct vnet, policy_id)
+#define v_key_int_random	offsetof(struct vnet, key_int_random)
+#define v_key_larval_lifetime	offsetof(struct vnet, key_larval_lifetime)
+#define v_key_blockacq_count	offsetof(struct vnet, key_blockacq_count)
+#define v_key_blockacq_lifetime	offsetof(struct vnet, key_blockacq_lifetime)
+#define v_key_preferred_oldsa	offsetof(struct vnet, key_preferred_oldsa)
+#define v_acq_seq		offsetof(struct vnet, acq_seq)
+#define v_key_tick_init_random	offsetof(struct vnet, key_tick_init_random)
+#define v_key_cb		offsetof(struct vnet, key_cb)
+#define v_ipsecstat		offsetof(struct vnet, ipsecstat)
+#define v_ip4_ah_cleartos	offsetof(struct vnet, ip4_ah_cleartos)
+#define v_ip4_ah_offsetmask	offsetof(struct vnet, ip4_ah_offsetmask)
+#define v_ip4_ipsec_dfbit	offsetof(struct vnet, ip4_ipsec_dfbit)
+#define v_ip4_esp_trans_deflev	offsetof(struct vnet, ip4_esp_trans_deflev)
+#define v_ip4_esp_net_deflev	offsetof(struct vnet, ip4_esp_net_deflev)
+#define v_ip4_ah_trans_deflev	offsetof(struct vnet, ip4_ah_trans_deflev)
+#define v_ip4_ah_net_deflev	offsetof(struct vnet, ip4_ah_net_deflev)
+#define v_ip4_def_policy	offsetof(struct vnet, ip4_def_policy)
+#define v_ip4_ipsec_ecn		offsetof(struct vnet, ip4_ipsec_ecn)
+#define v_ip4_esp_randpad	offsetof(struct vnet, ip4_esp_randpad)
+#define v_ipsec6stat		offsetof(struct vnet, ipsec6stat)
+#define v_ip6_esp_trans_deflev	offsetof(struct vnet, ip6_esp_trans_deflev)
+#define v_ip6_esp_net_deflev	offsetof(struct vnet, ip6_esp_net_deflev)
+#define v_ip6_ah_trans_deflev	offsetof(struct vnet, ip6_ah_trans_deflev)
+#define v_ip6_ah_net_deflev	offsetof(struct vnet, ip6_ah_net_deflev)
+#define v_ip6_def_policy	offsetof(struct vnet, ip6_def_policy)
+#define v_ip6_ipsec_ecn		offsetof(struct vnet, ip6_ipsec_ecn)
+#define v_ip6_esp_randpad	offsetof(struct vnet, ip6_esp_randpad)
 
 #endif _KERNEL
 
diff -urN sys/netinet/ip_encap.c sys.CORE/netinet/ip_encap.c
--- sys/netinet/ip_encap.c	Wed Jan 31 15:57:05 2007
+++ sys.CORE/netinet/ip_encap.c	Wed Jan 31 16:02:43 2007
@@ -151,6 +151,7 @@
 
 	match = NULL;
 	matchprio = 0;
+
 	for (ep = LIST_FIRST(&vnet->encaptab); ep; ep = LIST_NEXT(ep, chain)) {
 		if (ep->af != AF_INET)
 			continue;
@@ -228,7 +229,7 @@
 	const struct ip6protosw *psw;
 	struct encaptab *ep, *match;
 	int prio, matchprio;
-	struct vnet *vnet = m->m_pkthdr.rcvif->if_vnet;
+	struct vnet *vnet = m->m_pkthdr.rcvif->if_vnet;
 
 	ip6 = mtod(m, struct ip6_hdr *);
 
@@ -378,7 +379,7 @@
 encap_attach_func(af, proto, func, psw, arg, vnet)
 	int af;
 	int proto;
-	int (*func) __P((const struct mbuf *, int, int, void *));
+	int (*func) __P((const struct mbuf *, int, int, void *, struct vnet *));
 	const struct protosw *psw;
 	void *arg;
 	struct vnet *vnet;
@@ -450,6 +451,8 @@
 	u_int8_t *r;
 	int matchlen;
 
+	char *inetadd;
+
 	if (sp->sa_len > sizeof(s) || dp->sa_len > sizeof(d))
 		return 0;
 	if (sp->sa_family != ep->af || dp->sa_family != ep->af)
@@ -483,11 +486,24 @@
 	d.ss_len = dp->sa_len;
 	d.ss_family = dp->sa_family;
 
-	if (bcmp(&s, &ep->src, ep->src.ss_len) == 0 &&
+ 	if (bcmp(&s, &ep->src, ep->src.ss_len) == 0 &&
 	    bcmp(&d, &ep->dst, ep->dst.ss_len) == 0) {
 		return matchlen;
-	} else
-		return 0;
+	/*Boeing IDC MTUN IPv4 case*/
+	} else if ((ep->src.ss_family == AF_INET) && 
+		   (IN_MULTICAST(ntohl(((struct sockaddr_in*)&ep->dst)->sin_addr.s_addr ))) &&
+		   (IN_MULTICAST(ntohl(((struct sockaddr_in*)sp)->sin_addr.s_addr ))) &&
+		   (bcmp(&s, &ep->dst, ep->src.ss_len) == 0)) {
+	        return matchlen+1;
+	/*Boeing IDC MTUN IPv6 case*/
+	} else if ((ep->src.ss_family == AF_INET6) && 
+		   (IN6_IS_ADDR_MULTICAST(&(((struct sockaddr_in6*)&ep->dst)->sin6_addr))) &&
+		   (IN6_IS_ADDR_MULTICAST(&(((struct sockaddr_in6*)sp)->sin6_addr))) &&
+		   (bcmp(&s, &ep->dst, ep->src.ss_len) == 0)) {
+		return matchlen+1;
+	} else {
+	        return 0;
+	}
 }
 
 static void
diff -urN sys/netinet/ip_encap.h sys.CORE/netinet/ip_encap.h
--- sys/netinet/ip_encap.h	Wed Jan 31 15:57:05 2007
+++ sys.CORE/netinet/ip_encap.h	Wed Jan 31 16:02:43 2007
@@ -57,7 +57,7 @@
 	const struct sockaddr *, const struct protosw *, void *,
 	struct vnet *);
 const struct encaptab *encap_attach_func(int, int,
-	int (*)(const struct mbuf *, int, int, void *),
+	int (*)(const struct mbuf *, int, int, void *, struct vnet *),
 	const struct protosw *, void *, struct vnet *);
 int	encap_detach(const struct encaptab *, struct vnet *);
 void	*encap_getarg(struct mbuf *);
diff -urN sys/netinet/ip_icmp.c sys.CORE/netinet/ip_icmp.c
--- sys/netinet/ip_icmp.c	Wed Jan 31 15:57:05 2007
+++ sys.CORE/netinet/ip_icmp.c	Wed Jan 31 16:02:43 2007
@@ -600,7 +600,7 @@
 		  (struct sockaddr *)&icmpgw, (struct rtentry **)0, vnet);
 		pfctlinput(PRC_REDIRECT_HOST, (struct sockaddr *)&icmpsrc, vnet);
 #ifdef IPSEC
-		key_sa_routechange((struct sockaddr *)&icmpsrc);
+		key_sa_routechange((struct sockaddr *)&icmpsrc, vnet);
 #endif
 		break;
 
diff -urN sys/netinet/ip_input.c sys.CORE/netinet/ip_input.c
--- sys/netinet/ip_input.c	Wed Jan 31 15:57:05 2007
+++ sys.CORE/netinet/ip_input.c	Wed Jan 31 16:02:43 2007
@@ -694,8 +694,8 @@
 		/*
 		 * Enforce inbound IPsec SPD.
 		 */
-		if (ipsec4_in_reject(m, NULL)) {
-			ipsecstat.in_polvio++;
+		if (ipsec4_in_reject(m, NULL, vnet)) {
+			vnet->ipsecstat.in_polvio++;
 			goto bad;
 		}
 #endif /* IPSEC */
@@ -903,8 +903,8 @@
 	 * code - like udp/tcp/raw ip.
 	 */
 	if ((inetsw[ip_protox[ip->ip_p]].pr_flags & PR_LASTHDR) != 0 &&
-	    ipsec4_in_reject(m, NULL)) {
-		ipsecstat.in_polvio++;
+	    ipsec4_in_reject(m, NULL, vnet)) {
+		vnet->ipsecstat.in_polvio++;
 		goto bad;
 	}
 #endif
@@ -1970,7 +1970,7 @@
 			sp = ipsec4_getpolicybyaddr(mcopy,
 						    IPSEC_DIR_OUTBOUND,
 			                            IP_FORWARDING,
-			                            &ipsecerror);
+			                            &ipsecerror, vnet);
 
 			if (sp == NULL)
 				destifp = vnet->ipforward_rt.ro_rt->rt_ifp;
@@ -1978,7 +1978,7 @@
 				/* count IPsec header size */
 				ipsechdr = ipsec4_hdrsiz(mcopy,
 							 IPSEC_DIR_OUTBOUND,
-							 NULL);
+							 NULL, vnet);
 
 				/*
 				 * find the correct route for outer IPv4
@@ -2029,7 +2029,7 @@
 				/* count IPsec header size */
 				ipsechdr = ipsec4_hdrsiz(mcopy,
 							 IPSEC_DIR_OUTBOUND,
-							 NULL);
+							 NULL, vnet);
 
 				/*
 				 * find the correct route for outer IPv4
diff -urN sys/netinet/ip_output.c sys.CORE/netinet/ip_output.c
--- sys/netinet/ip_output.c	Wed Jan 31 15:57:05 2007
+++ sys.CORE/netinet/ip_output.c	Wed Jan 31 16:02:43 2007
@@ -320,14 +320,22 @@
 		 * See if the caller provided any multicast options
 		 */
 		if (imo != NULL) {
-			ip->ip_ttl = imo->imo_multicast_ttl;
+			/* Boeing IDC to handle divert re-injection 
+			 * If you don't want the TTL to be modified then 
+			 * set the multicast_ttl socket option to zero.
+			 */
+		        if (imo->imo_multicast_ttl != 0){
+			  ip->ip_ttl = imo->imo_multicast_ttl;
+			}
 			if (imo->imo_multicast_vif != -1)
 				ip->ip_src.s_addr =
 				    ip_mcast_src ?
 				    ip_mcast_src(imo->imo_multicast_vif, vnet) :
 				    INADDR_ANY;
-		} else
-			ip->ip_ttl = IP_DEFAULT_MULTICAST_TTL;
+		} else {
+		  ip->ip_ttl = IP_DEFAULT_MULTICAST_TTL;
+		} 
+
 		/*
 		 * Confirm that the outgoing interface supports multicast.
 		 */
@@ -459,12 +467,12 @@
 #ifdef IPSEC
 	/* get SP for this packet */
 	if (so == NULL)
-		sp = ipsec4_getpolicybyaddr(m, IPSEC_DIR_OUTBOUND, flags, &error);
+		sp = ipsec4_getpolicybyaddr(m, IPSEC_DIR_OUTBOUND, flags, &error, vnet);
 	else
 		sp = ipsec4_getpolicybysock(m, IPSEC_DIR_OUTBOUND, so, &error);
 
 	if (sp == NULL) {
-		ipsecstat.out_inval++;
+		vnet->ipsecstat.out_inval++;
 		goto bad;
 	}
 
@@ -476,7 +484,7 @@
 		/*
 		 * This packet is just discarded.
 		 */
-		ipsecstat.out_polvio++;
+		vnet->ipsecstat.out_polvio++;
 		goto bad;
 
 	case IPSEC_POLICY_BYPASS:
diff -urN sys/netinet/raw_ip.c sys.CORE/netinet/raw_ip.c
--- sys/netinet/raw_ip.c	Wed Jan 31 15:57:05 2007
+++ sys.CORE/netinet/raw_ip.c	Wed Jan 31 16:02:43 2007
@@ -184,9 +184,9 @@
 
 #ifdef IPSEC
 			/* check AH/ESP integrity. */
-			if (n && ipsec4_in_reject_so(n, last->inp_socket)) {
+			if (n && ipsec4_in_reject_so(n, last->inp_socket, vnet)) {
 				m_freem(n);
-				ipsecstat.in_polvio++;
+				vnet->ipsecstat.in_polvio++;
 				/* do not inject data to pcb */
 			} else
 #endif /*IPSEC*/
@@ -217,9 +217,9 @@
 	}
 #ifdef IPSEC
 	/* check AH/ESP integrity. */
-	if (last && ipsec4_in_reject_so(m, last->inp_socket)) {
+	if (last && ipsec4_in_reject_so(m, last->inp_socket, vnet)) {
 		m_freem(m);
-		ipsecstat.in_polvio++;
+		vnet->ipsecstat.in_polvio++;
 		vnet->ipstat.ips_delivered--;
 		/* do not inject data to pcb */
 	} else
diff -urN sys/netinet/tcp_input.c sys.CORE/netinet/tcp_input.c
--- sys/netinet/tcp_input.c	Wed Jan 31 15:57:05 2007
+++ sys.CORE/netinet/tcp_input.c	Wed Jan 31 16:02:43 2007
@@ -580,13 +580,15 @@
 
 #ifdef IPSEC
 	if (isipv6) {
-		if (inp != NULL && ipsec6_in_reject_so(m, inp->inp_socket)) {
-			ipsec6stat.in_polvio++;
+#ifdef INET6
+		if (inp != NULL && ipsec6_in_reject_so(m, inp->inp_socket, vnet)) {
+			vnet->ipsec6stat.in_polvio++;
 			goto drop;
 		}
+#endif
 	} else {
-		if (inp != NULL && ipsec4_in_reject_so(m, inp->inp_socket)) {
-			ipsecstat.in_polvio++;
+		if (inp != NULL && ipsec4_in_reject_so(m, inp->inp_socket, vnet)) {
+			vnet->ipsecstat.in_polvio++;
 			goto drop;
 		}
 	}
diff -urN sys/netinet/tcp_subr.c sys.CORE/netinet/tcp_subr.c
--- sys/netinet/tcp_subr.c	Wed Jan 31 15:57:05 2007
+++ sys.CORE/netinet/tcp_subr.c	Wed Jan 31 16:02:43 2007
@@ -1468,9 +1468,13 @@
 	struct ip6_hdr *ip6;
 #endif /* INET6 */
 	struct tcphdr *th;
+	struct vnet *vnet;
 
 	if ((tp == NULL) || ((inp = tp->t_inpcb) == NULL))
 		return 0;
+	vnet = tp->t_vnet;
+	if (vnet == NULL)
+		panic("ipsec_hdrsiz_tcp: NULL vnet was passed.");
 	MGETHDR(m, M_DONTWAIT, MT_DATA);
 	if (!m)
 		return 0;
@@ -1482,7 +1486,7 @@
 		m->m_pkthdr.len = m->m_len =
 			sizeof(struct ip6_hdr) + sizeof(struct tcphdr);
 		tcp_fillheaders(tp, ip6, th);
-		hdrsiz = ipsec6_hdrsiz(m, IPSEC_DIR_OUTBOUND, inp);
+		hdrsiz = ipsec6_hdrsiz(m, IPSEC_DIR_OUTBOUND, inp, vnet);
 	} else
 #endif /* INET6 */
       {
@@ -1490,7 +1494,7 @@
 	th = (struct tcphdr *)(ip + 1);
 	m->m_pkthdr.len = m->m_len = sizeof(struct tcpiphdr);
 	tcp_fillheaders(tp, ip, th);
-	hdrsiz = ipsec4_hdrsiz(m, IPSEC_DIR_OUTBOUND, inp);
+	hdrsiz = ipsec4_hdrsiz(m, IPSEC_DIR_OUTBOUND, inp, vnet);
       }
 
 	m_free(m);
diff -urN sys/netinet/udp_usrreq.c sys.CORE/netinet/udp_usrreq.c
--- sys/netinet/udp_usrreq.c	Wed Jan 31 15:57:05 2007
+++ sys.CORE/netinet/udp_usrreq.c	Wed Jan 31 16:02:43 2007
@@ -325,8 +325,8 @@
 
 #ifdef IPSEC
 				/* check AH/ESP integrity. */
-				if (ipsec4_in_reject_so(m, last->inp_socket))
-					ipsecstat.in_polvio++;
+				if (ipsec4_in_reject_so(m, last->inp_socket, vnet))
+					vnet->ipsecstat.in_polvio++;
 					/* do not inject data to pcb */
 				else
 #endif /*IPSEC*/
@@ -365,8 +365,8 @@
 		}
 #ifdef IPSEC
 		/* check AH/ESP integrity. */
-		if (ipsec4_in_reject_so(m, last->inp_socket)) {
-			ipsecstat.in_polvio++;
+		if (ipsec4_in_reject_so(m, last->inp_socket, vnet)) {
+			vnet->ipsecstat.in_polvio++;
 			goto bad;
 		}
 #endif /*IPSEC*/
@@ -410,8 +410,8 @@
 		return;
 	}
 #ifdef IPSEC
-	if (ipsec4_in_reject_so(m, inp->inp_socket)) {
-		ipsecstat.in_polvio++;
+	if (ipsec4_in_reject_so(m, inp->inp_socket, vnet)) {
+		vnet->ipsecstat.in_polvio++;
 		goto bad;
 	}
 #endif /*IPSEC*/
diff -urN sys/netinet6/ah.h sys.CORE/netinet6/ah.h
--- sys/netinet6/ah.h	Sat Apr 27 22:40:26 2002
+++ sys.CORE/netinet6/ah.h	Wed Jan 31 16:02:43 2007
@@ -86,9 +86,9 @@
 
 extern size_t ah_hdrsiz __P((struct ipsecrequest *));
 extern void ah4_input __P((struct mbuf *, ...));
-extern int ah4_output __P((struct mbuf *, struct ipsecrequest *));
+extern int ah4_output __P((struct mbuf *, struct ipsecrequest *, struct vnet*));
 extern int ah4_calccksum __P((struct mbuf *, caddr_t, size_t,
-	const struct ah_algorithm *, struct secasvar *));
+	const struct ah_algorithm *, struct secasvar *, struct vnet *));
 #endif /* _KERNEL */
 
 #endif /* _NETINET6_AH_H_ */
diff -urN sys/netinet6/ah_core.c sys.CORE/netinet6/ah_core.c
--- sys/netinet6/ah_core.c	Sat Apr 27 22:40:26 2002
+++ sys.CORE/netinet6/ah_core.c	Wed Jan 31 16:02:43 2007
@@ -52,6 +52,7 @@
 #include <sys/time.h>
 #include <sys/syslog.h>
 
+#include <net/vnet.h>
 #include <net/if.h>
 #include <net/route.h>
 
@@ -1181,12 +1182,13 @@
  * Don't use m_copy(), it will try to share cluster mbuf by using refcnt.
  */
 int
-ah4_calccksum(m, ahdat, len, algo, sav)
+ah4_calccksum(m, ahdat, len, algo, sav, vnet)
 	struct mbuf *m;
 	caddr_t ahdat;
 	size_t len;
 	const struct ah_algorithm *algo;
 	struct secasvar *sav;
+	struct vnet *vnet;
 {
 	int off;
 	int hdrtype;
@@ -1200,6 +1202,9 @@
 	if ((m->m_flags & M_PKTHDR) == 0)
 		return EINVAL;
 
+	if (vnet == NULL)
+		panic("ah4_calccksum: NULL vnet was passed.");
+
 	ahseen = 0;
 	hdrtype = -1;	/* dummy, it is called IPPROTO_IP */
 
@@ -1231,9 +1236,9 @@
 #endif
 		iphdr.ip_ttl = 0;
 		iphdr.ip_sum = htons(0);
-		if (ip4_ah_cleartos)
+		if (vnet->ip4_ah_cleartos)
 			iphdr.ip_tos = 0;
-		iphdr.ip_off = htons(ntohs(iphdr.ip_off) & ip4_ah_offsetmask);
+		iphdr.ip_off = htons(ntohs(iphdr.ip_off) & vnet->ip4_ah_offsetmask);
 		(algo->update)(&algos, (caddr_t)&iphdr, sizeof(struct ip));
 
 		if (hlen != sizeof(struct ip)) {
diff -urN sys/netinet6/ah_input.c sys.CORE/netinet6/ah_input.c
--- sys/netinet6/ah_input.c	Wed Jan 31 15:57:05 2007
+++ sys.CORE/netinet6/ah_input.c	Wed Jan 31 16:02:43 2007
@@ -87,6 +87,8 @@
 #define	KEYDEBUG(lev,arg)
 #endif
 
+#include <net/vnet.h>
+
 #include <machine/stdarg.h>
 
 #include <net/net_osdep.h>
@@ -120,19 +122,25 @@
 	int off, proto;
 	va_list ap;
 	size_t stripsiz = 0;
+	struct vnet *vnet;
 
 	va_start(ap, m);
 	off = va_arg(ap, int);
 	proto = va_arg(ap, int);
 	va_end(ap);
 
+	if (m == NULL || m->m_pkthdr.rcvif == NULL)
+		panic("ah4_input: cannot find vnet.");
+	vnet = m->m_pkthdr.rcvif->if_vnet;
+	if (vnet == NULL)
+		panic("ah4_input: NULL vnet passed.");
 #ifndef PULLDOWN_TEST
 	if (m->m_len < off + sizeof(struct newah)) {
 		m = m_pullup(m, off + sizeof(struct newah));
 		if (!m) {
 			ipseclog((LOG_DEBUG, "IPv4 AH input: can't pullup;"
 				"dropping the packet for simplicity\n"));
-			ipsecstat.in_inval++;
+			vnet->ipsecstat.in_inval++;
 			goto fail;
 		}
 	}
@@ -145,7 +153,7 @@
 	if (ah == NULL) {
 		ipseclog((LOG_DEBUG, "IPv4 AH input: can't pullup;"
 			"dropping the packet for simplicity\n"));
-		ipsecstat.in_inval++;
+		vnet->ipsecstat.in_inval++;
 		goto fail;
 	}
 #endif
@@ -161,11 +169,11 @@
 
 	if ((sav = key_allocsa(AF_INET,
 	                      (caddr_t)&ip->ip_src, (caddr_t)&ip->ip_dst,
-	                      IPPROTO_AH, spi)) == 0) {
+	                      IPPROTO_AH, spi, vnet)) == 0) {
 		ipseclog((LOG_WARNING,
 		    "IPv4 AH input: no key association found for spi %u\n",
 		    (u_int32_t)ntohl(spi)));
-		ipsecstat.in_nosa++;
+		vnet->ipsecstat.in_nosa++;
 		goto fail;
 	}
 	KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
@@ -175,7 +183,7 @@
 		ipseclog((LOG_DEBUG,
 		    "IPv4 AH input: non-mature/dying SA found for spi %u\n",
 		    (u_int32_t)ntohl(spi)));
-		ipsecstat.in_badspi++;
+		vnet->ipsecstat.in_badspi++;
 		goto fail;
 	}
 
@@ -184,7 +192,7 @@
 		ipseclog((LOG_DEBUG, "IPv4 AH input: "
 		    "unsupported authentication algorithm for spi %u\n",
 		    (u_int32_t)ntohl(spi)));
-		ipsecstat.in_badspi++;
+		vnet->ipsecstat.in_badspi++;
 		goto fail;
 	}
 
@@ -225,7 +233,7 @@
 		    "(%lu, should be at least %lu): %s\n",
 		    (u_long)siz1, (u_long)siz,
 		    ipsec4_logpacketstr(ip, spi)));
-		ipsecstat.in_inval++;
+		vnet->ipsecstat.in_inval++;
 		goto fail;
 	}
 	if ((ah->ah_len << 2) - sizoff != siz1) {
@@ -233,7 +241,7 @@
 		    "(%d should be %lu): %s\n",
 		    (ah->ah_len << 2) - sizoff, (u_long)siz1,
 		    ipsec4_logpacketstr(ip, spi)));
-		ipsecstat.in_inval++;
+		vnet->ipsecstat.in_inval++;
 		goto fail;
 	}
 
@@ -242,7 +250,7 @@
 		m = m_pullup(m, off + sizeof(struct ah) + sizoff + siz1);
 		if (!m) {
 			ipseclog((LOG_DEBUG, "IPv4 AH input: can't pullup\n"));
-			ipsecstat.in_inval++;
+			vnet->ipsecstat.in_inval++;
 			goto fail;
 		}
 
@@ -254,7 +262,7 @@
 		sizeof(struct ah) + sizoff + siz1);
 	if (ah == NULL) {
 		ipseclog((LOG_DEBUG, "IPv4 AH input: can't pullup\n"));
-		ipsecstat.in_inval++;
+		vnet->ipsecstat.in_inval++;
 		goto fail;
 	}
 #endif
@@ -267,7 +275,7 @@
 		if (ipsec_chkreplay(ntohl(((struct newah *)ah)->ah_seq), sav))
 			; /* okey */
 		else {
-			ipsecstat.in_ahreplay++;
+			vnet->ipsecstat.in_ahreplay++;
 			ipseclog((LOG_WARNING,
 			    "replay packet in IPv4 AH input: %s %s\n",
 			    ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav)));
@@ -283,7 +291,7 @@
 	if (!cksum) {
 		ipseclog((LOG_DEBUG, "IPv4 AH input: "
 		    "couldn't alloc temporary region for cksum\n"));
-		ipsecstat.in_inval++;
+		vnet->ipsecstat.in_inval++;
 		goto fail;
 	}
 	
@@ -293,12 +301,12 @@
 	 */
 	ip->ip_len = htons(ip->ip_len + hlen);
 	ip->ip_off = htons(ip->ip_off);
-	if (ah4_calccksum(m, (caddr_t)cksum, siz1, algo, sav)) {
+	if (ah4_calccksum(m, (caddr_t)cksum, siz1, algo, sav, vnet)) {
 		free(cksum, M_TEMP);
-		ipsecstat.in_inval++;
+		vnet->ipsecstat.in_inval++;
 		goto fail;
 	}
-	ipsecstat.in_ahhist[sav->alg_auth]++;
+	vnet->ipsecstat.in_ahhist[sav->alg_auth]++;
 	/*
 	 * flip them back.
 	 */
@@ -321,7 +329,7 @@
 		    "checksum mismatch in IPv4 AH input: %s %s\n",
 		    ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav)));
 		free(cksum, M_TEMP);
-		ipsecstat.in_ahauthfail++;
+		vnet->ipsecstat.in_ahauthfail++;
 		goto fail;
 	}
     }
@@ -374,12 +382,12 @@
 		ipseclog((LOG_DEBUG,
 		    "IPv4 AH input: authentication succeess\n"));
 #endif
-		ipsecstat.in_ahauthsucc++;
+		vnet->ipsecstat.in_ahauthsucc++;
 	} else {
 		ipseclog((LOG_WARNING,
 		    "authentication failed in IPv4 AH input: %s %s\n",
 		    ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav)));
-		ipsecstat.in_ahauthfail++;
+		vnet->ipsecstat.in_ahauthfail++;
 		goto fail;
 	}
 
@@ -388,7 +396,7 @@
 	 */
 	if ((sav->flags & SADB_X_EXT_OLD) == 0 && sav->replay) {
 		if (ipsec_updatereplay(ntohl(((struct newah *)ah)->ah_seq), sav)) {
-			ipsecstat.in_ahreplay++;
+			vnet->ipsecstat.in_ahreplay++;
 			goto fail;
 		}
 	}
@@ -416,19 +424,19 @@
 		if (m->m_len < sizeof(*ip)) {
 			m = m_pullup(m, sizeof(*ip));
 			if (!m) {
-				ipsecstat.in_inval++;
+				vnet->ipsecstat.in_inval++;
 				goto fail;
 			}
 		}
 		ip = mtod(m, struct ip *);
 		/* ECN consideration. */
-		ip_ecn_egress(ip4_ipsec_ecn, &tos, &ip->ip_tos);
+		ip_ecn_egress(vnet->ip4_ipsec_ecn, &tos, &ip->ip_tos);
 		if (!key_checktunnelsanity(sav, AF_INET,
 			    (caddr_t)&ip->ip_src, (caddr_t)&ip->ip_dst)) {
 			ipseclog((LOG_NOTICE, "ipsec tunnel address mismatch "
 			    "in IPv4 AH input: %s %s\n",
 			    ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav)));
-			ipsecstat.in_inval++;
+			vnet->ipsecstat.in_inval++;
 			goto fail;
 		}
 
@@ -459,13 +467,13 @@
 		key_sa_recordxfer(sav, m);
 		if (ipsec_addhist(m, IPPROTO_AH, spi) != 0 ||
 		    ipsec_addhist(m, IPPROTO_IPV4, 0) != 0) {
-			ipsecstat.in_nomem++;
+			vnet->ipsecstat.in_nomem++;
 			goto fail;
 		}
 
 		s = splimp();
 		if (IF_QFULL(&g_ipintrq)) {
-			ipsecstat.in_inval++;
+			vnet->ipsecstat.in_inval++;
 			splx(s);
 			goto fail;
 		}
@@ -521,7 +529,7 @@
 		if (m->m_len < sizeof(*ip)) {
 			m = m_pullup(m, sizeof(*ip));
 			if (m == NULL) {
-				ipsecstat.in_inval++;
+				vnet->ipsecstat.in_inval++;
 				goto fail;
 			}
 		}
@@ -536,14 +544,14 @@
 
 		key_sa_recordxfer(sav, m);
 		if (ipsec_addhist(m, IPPROTO_AH, spi) != 0) {
-			ipsecstat.in_nomem++;
+			vnet->ipsecstat.in_nomem++;
 			goto fail;
 		}
 
 		if (nxt != IPPROTO_DONE) {
 			if ((inetsw[ip_protox[nxt]].pr_flags & PR_LASTHDR) != 0 &&
-			    ipsec4_in_reject(m, NULL)) {
-				ipsecstat.in_polvio++;
+			    ipsec4_in_reject(m, NULL, vnet)) {
+				vnet->ipsecstat.in_polvio++;
 				goto fail;
 			}
 			(*inetsw[ip_protox[nxt]].pr_input)(m, off, nxt);
@@ -557,7 +565,7 @@
 			printf("DP ah4_input call free SA:%p\n", sav));
 		key_freesav(sav);
 	}
-	ipsecstat.in_success++;
+	vnet->ipsecstat.in_success++;
 	return;
 
 fail:
@@ -591,7 +599,12 @@
 	u_int16_t nxt;
 	int s;
 	size_t stripsiz = 0;
+	struct vnet *vnet;
 
+	if (m == NULL || m->m_pkthdr.rcvif == NULL)
+		panic("ah6_input: cannot find vnet.");
+	vnet = m->m_pkthdr.rcvif->if_vnet;
+	if (vnet == NULL)
 #ifndef PULLDOWN_TEST
 	IP6_EXTHDR_CHECK(m, off, sizeof(struct ah), IPPROTO_DONE);
 	ah = (struct ah *)(mtod(m, caddr_t) + off);
@@ -599,7 +612,7 @@
 	IP6_EXTHDR_GET(ah, struct ah *, m, off, sizeof(struct newah));
 	if (ah == NULL) {
 		ipseclog((LOG_DEBUG, "IPv6 AH input: can't pullup\n"));
-		ipsec6stat.in_inval++;
+		vnet->ipsec6stat.in_inval++;
 		return IPPROTO_DONE;
 	}
 #endif
@@ -612,17 +625,17 @@
 	if (ntohs(ip6->ip6_plen) == 0) {
 		ipseclog((LOG_ERR, "IPv6 AH input: "
 		    "AH with IPv6 jumbogram is not supported.\n"));
-		ipsec6stat.in_inval++;
+		vnet->ipsec6stat.in_inval++;
 		goto fail;
 	}
 
 	if ((sav = key_allocsa(AF_INET6,
 	                      (caddr_t)&ip6->ip6_src, (caddr_t)&ip6->ip6_dst,
-	                      IPPROTO_AH, spi)) == 0) {
+	                      IPPROTO_AH, spi, vnet)) == 0) {
 		ipseclog((LOG_WARNING,
 		    "IPv6 AH input: no key association found for spi %u\n",
 		    (u_int32_t)ntohl(spi)));
-		ipsec6stat.in_nosa++;
+		vnet->ipsec6stat.in_nosa++;
 		goto fail;
 	}
 	KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
@@ -632,7 +645,7 @@
 		ipseclog((LOG_DEBUG,
 		    "IPv6 AH input: non-mature/dying SA found for spi %u; ",
 		    (u_int32_t)ntohl(spi)));
-		ipsec6stat.in_badspi++;
+		vnet->ipsec6stat.in_badspi++;
 		goto fail;
 	}
 
@@ -641,7 +654,7 @@
 		ipseclog((LOG_DEBUG, "IPv6 AH input: "
 		    "unsupported authentication algorithm for spi %u\n",
 		    (u_int32_t)ntohl(spi)));
-		ipsec6stat.in_badspi++;
+		vnet->ipsec6stat.in_badspi++;
 		goto fail;
 	}
 
@@ -665,7 +678,7 @@
 		    "(%lu, should be at least %lu): %s\n",
 		    (u_long)siz1, (u_long)siz,
 		    ipsec6_logpacketstr(ip6, spi)));
-		ipsec6stat.in_inval++;
+		vnet->ipsec6stat.in_inval++;
 		goto fail;
 	}
 	if ((ah->ah_len << 2) - sizoff != siz1) {
@@ -673,7 +686,7 @@
 		    "(%d should be %lu): %s\n",
 		    (ah->ah_len << 2) - sizoff, (u_long)siz1,
 		    ipsec6_logpacketstr(ip6, spi)));
-		ipsec6stat.in_inval++;
+		vnet->ipsec6stat.in_inval++;
 		goto fail;
 	}
 #ifndef PULLDOWN_TEST
@@ -683,7 +696,7 @@
 		sizeof(struct ah) + sizoff + siz1);
 	if (ah == NULL) {
 		ipseclog((LOG_NOTICE, "couldn't pullup gather IPv6 AH checksum part"));
-		ipsec6stat.in_inval++;
+		vnet->ipsec6stat.in_inval++;
 		m = NULL;
 		goto fail;
 	}
@@ -697,7 +710,7 @@
 		if (ipsec_chkreplay(ntohl(((struct newah *)ah)->ah_seq), sav))
 			; /* okey */
 		else {
-			ipsec6stat.in_ahreplay++;
+			vnet->ipsec6stat.in_ahreplay++;
 			ipseclog((LOG_WARNING,
 			    "replay packet in IPv6 AH input: %s %s\n",
 			    ipsec6_logpacketstr(ip6, spi),
@@ -714,16 +727,16 @@
 	if (!cksum) {
 		ipseclog((LOG_DEBUG, "IPv6 AH input: "
 		    "couldn't alloc temporary region for cksum\n"));
-		ipsec6stat.in_inval++;
+		vnet->ipsec6stat.in_inval++;
 		goto fail;
 	}
 	
 	if (ah6_calccksum(m, (caddr_t)cksum, siz1, algo, sav)) {
 		free(cksum, M_TEMP);
-		ipsec6stat.in_inval++;
+		vnet->ipsec6stat.in_inval++;
 		goto fail;
 	}
-	ipsec6stat.in_ahhist[sav->alg_auth]++;
+	vnet->ipsec6stat.in_ahhist[sav->alg_auth]++;
 
     {
 	caddr_t sumpos = NULL;
@@ -741,7 +754,7 @@
 		    "checksum mismatch in IPv6 AH input: %s %s\n",
 		    ipsec6_logpacketstr(ip6, spi), ipsec_logsastr(sav)));
 		free(cksum, M_TEMP);
-		ipsec6stat.in_ahauthfail++;
+		vnet->ipsec6stat.in_ahauthfail++;
 		goto fail;
 	}
     }
@@ -786,12 +799,12 @@
 		ipseclog((LOG_DEBUG,
 		    "IPv6 AH input: authentication succeess\n"));
 #endif
-		ipsec6stat.in_ahauthsucc++;
+		vnet->ipsec6stat.in_ahauthsucc++;
 	} else {
 		ipseclog((LOG_WARNING,
 		    "authentication failed in IPv6 AH input: %s %s\n",
 		    ipsec6_logpacketstr(ip6, spi), ipsec_logsastr(sav)));
-		ipsec6stat.in_ahauthfail++;
+		vnet->ipsec6stat.in_ahauthfail++;
 		goto fail;
 	}
 
@@ -800,7 +813,7 @@
 	 */
 	if ((sav->flags & SADB_X_EXT_OLD) == 0 && sav->replay) {
 		if (ipsec_updatereplay(ntohl(((struct newah *)ah)->ah_seq), sav)) {
-			ipsec6stat.in_ahreplay++;
+			vnet->ipsec6stat.in_ahreplay++;
 			goto fail;
 		}
 	}
@@ -832,20 +845,20 @@
 			 */
 			m = m_pullup(m, sizeof(*ip6));
 			if (!m) {
-				ipsec6stat.in_inval++;
+				vnet->ipsec6stat.in_inval++;
 				goto fail;
 			}
 		}
 		ip6 = mtod(m, struct ip6_hdr *);
 		/* ECN consideration. */
-		ip6_ecn_egress(ip6_ipsec_ecn, &flowinfo, &ip6->ip6_flow);
+		ip6_ecn_egress(vnet->ip6_ipsec_ecn, &flowinfo, &ip6->ip6_flow);
 		if (!key_checktunnelsanity(sav, AF_INET6,
 			    (caddr_t)&ip6->ip6_src, (caddr_t)&ip6->ip6_dst)) {
 			ipseclog((LOG_NOTICE, "ipsec tunnel address mismatch "
 			    "in IPv6 AH input: %s %s\n",
 			    ipsec6_logpacketstr(ip6, spi),
 			    ipsec_logsastr(sav)));
-			ipsec6stat.in_inval++;
+			vnet->ipsec6stat.in_inval++;
 			goto fail;
 		}
 
@@ -861,17 +874,17 @@
 		key_sa_recordxfer(sav, m);
 		if (ipsec_addhist(m, IPPROTO_AH, spi) != 0 ||
 		    ipsec_addhist(m, IPPROTO_IPV6, 0) != 0) {
-			ipsec6stat.in_nomem++;
+			vnet->ipsec6stat.in_nomem++;
 			goto fail;
 		}
 
 		s = splimp();
-		if (IF_QFULL(&ip6intrq)) {
-			ipsec6stat.in_inval++;
+		if (IF_QFULL(&g_ip6intrq)) {
+			vnet->ipsec6stat.in_inval++;
 			splx(s);
 			goto fail;
 		}
-		IF_ENQUEUE(&ip6intrq, m);
+		IF_ENQUEUE(&g_ip6intrq, m);
 		m = NULL;
 		schednetisr(NETISR_IPV6); /* can be skipped but to make sure */
 		splx(s);
@@ -934,7 +947,7 @@
 
 		key_sa_recordxfer(sav, m);
 		if (ipsec_addhist(m, IPPROTO_AH, spi) != 0) {
-			ipsec6stat.in_nomem++;
+			vnet->ipsec6stat.in_nomem++;
 			goto fail;
 		}
 	}
@@ -947,7 +960,7 @@
 			printf("DP ah6_input call free SA:%p\n", sav));
 		key_freesav(sav);
 	}
-	ipsec6stat.in_success++;
+	vnet->ipsec6stat.in_success++;
 	return nxt;
 
 fail:
@@ -972,6 +985,7 @@
 	struct secasvar *sav;
 	struct ip6_hdr *ip6;
 	struct mbuf *m;
+	struct vnet *vnet = NULL;
 	struct ip6ctlparam *ip6cp = NULL;
 	int off;
 	struct sockaddr_in6 *sa6_src, *sa6_dst;
@@ -986,11 +1000,15 @@
 	if (d != NULL) {
 		ip6cp = (struct ip6ctlparam *)d;
 		m = ip6cp->ip6c_m;
+		if (m == NULL || m->m_pkthdr.rcvif == NULL)
+			panic("ah6_ctlinput:  cannot find vnet.");
+	        vnet = m->m_pkthdr.rcvif->if_vnet;
 		ip6 = ip6cp->ip6c_ip6;
 		off = ip6cp->ip6c_off;
 	} else {
 		m = NULL;
 		ip6 = NULL;
+		off = 0;
 	}
 
 	if (ip6) {
@@ -1025,7 +1043,7 @@
 			sav = key_allocsa(AF_INET6,
 					  (caddr_t)&sa6_src->sin6_addr,
 					  (caddr_t)&sa6_dst->sin6_addr,
-					  IPPROTO_AH, ahp->ah_spi);
+					  IPPROTO_AH, ahp->ah_spi, vnet);
 			if (sav) {
 				if (sav->state == SADB_SASTATE_MATURE ||
 				    sav->state == SADB_SASTATE_DYING)
@@ -1042,7 +1060,7 @@
 			 *   corresponding routing entry, or
 			 * - ignore the MTU change notification.
 			 */
-			icmp6_mtudisc_update((struct ip6ctlparam *)d, valid);
+			icmp6_mtudisc_update((struct ip6ctlparam *)d, valid, vnet);
 		}
 
 		/* we normally notify single pcb here */
diff -urN sys/netinet6/ah_output.c sys.CORE/netinet6/ah_output.c
--- sys/netinet6/ah_output.c	Mon May  5 23:46:58 2003
+++ sys.CORE/netinet6/ah_output.c	Wed Jan 31 16:02:43 2007
@@ -75,6 +75,7 @@
 #include <netkey/keydb.h>
 
 #include <net/net_osdep.h>
+#include <net/vnet.h>
 
 #ifdef INET
 static struct in_addr *ah4_finaldst __P((struct mbuf *));
@@ -142,9 +143,10 @@
  * the function does not modify m.
  */
 int
-ah4_output(m, isr)
+ah4_output(m, isr, vnet)
 	struct mbuf *m;
 	struct ipsecrequest *isr;
+	struct vnet *vnet;
 {
 	struct secasvar *sav = isr->sav;
 	const struct ah_algorithm *algo;
@@ -159,6 +161,8 @@
 	struct in_addr *finaldst;
 	int error;
 
+	if (vnet == NULL)
+		panic("ah4_output: NULL vnet was passed.");
 	/* sanity checks */
 	if ((sav->flags & SADB_X_EXT_OLD) == 0 && !sav->replay) {
 		struct ip *ip;
@@ -169,7 +173,7 @@
 			(u_int32_t)ntohl(ip->ip_src.s_addr),
 			(u_int32_t)ntohl(ip->ip_dst.s_addr),
 			(u_int32_t)ntohl(sav->spi)));
-		ipsecstat.out_inval++;
+		vnet->ipsecstat.out_inval++;
 		m_freem(m);
 		return EINVAL;
 	}
@@ -178,7 +182,7 @@
 	if (!algo) {
 		ipseclog((LOG_ERR, "ah4_output: unsupported algorithm: "
 		    "SPI=%u\n", (u_int32_t)ntohl(sav->spi)));
-		ipsecstat.out_inval++;
+		vnet->ipsecstat.out_inval++;
 		m_freem(m);
 		return EINVAL;
 	}
@@ -260,7 +264,7 @@
 				ipseclog((LOG_WARNING,
 				    "replay counter overflowed. %s\n",
 				    ipsec_logsastr(sav)));
-				ipsecstat.out_inval++;
+				vnet->ipsecstat.out_inval++;
 				m_freem(m);
 				return EINVAL;
 			}
@@ -282,7 +286,7 @@
 		ip->ip_len = htons(ntohs(ip->ip_len) + ahlen);
 	else {
 		ipseclog((LOG_ERR, "IPv4 AH output: size exceeds limit\n"));
-		ipsecstat.out_inval++;
+		vnet->ipsecstat.out_inval++;
 		m_freem(m);
 		return EMSGSIZE;
 	}
@@ -304,13 +308,13 @@
 	 * calcurate the checksum, based on security association
 	 * and the algorithm specified.
 	 */
-	error = ah4_calccksum(m, (caddr_t)ahsumpos, plen, algo, sav);
+	error = ah4_calccksum(m, (caddr_t)ahsumpos, plen, algo, sav, vnet);
 	if (error) {
 		ipseclog((LOG_ERR,
 		    "error after ah4_calccksum, called from ah4_output"));
 		m_freem(m);
 		m = NULL;
-		ipsecstat.out_inval++;
+		vnet->ipsecstat.out_inval++;
 		return error;
 	}
 
@@ -318,8 +322,8 @@
 		ip = mtod(m, struct ip *);	/* just to make sure */
 		ip->ip_dst.s_addr = dst.s_addr;
 	}
-	ipsecstat.out_success++;
-	ipsecstat.out_ahhist[sav->alg_auth]++;
+	vnet->ipsecstat.out_success++;
+	vnet->ipsecstat.out_ahhist[sav->alg_auth]++;
 	key_sa_recordxfer(sav, m);
 
 	return 0;
@@ -371,6 +375,11 @@
 	int error = 0;
 	int ahlen;
 	struct ip6_hdr *ip6;
+	struct vnet *vnet;
+
+	if (m == NULL || m->m_pkthdr.rcvif == NULL)
+		panic("ah6_output: unable to find vnet.");
+	vnet = m->m_pkthdr.rcvif->if_vnet;
 
 	if (m->m_len < sizeof(struct ip6_hdr)) {
 		ipseclog((LOG_DEBUG, "ah6_output: first mbuf too short\n"));
@@ -422,7 +431,7 @@
 		ipseclog((LOG_DEBUG, "ah6_output: internal error: "
 			"sav->replay is null: SPI=%u\n",
 			(u_int32_t)ntohl(sav->spi)));
-		ipsec6stat.out_inval++;
+		vnet->ipsec6stat.out_inval++;
 		m_freem(m);
 		return EINVAL;
 	}
@@ -431,7 +440,7 @@
 	if (!algo) {
 		ipseclog((LOG_ERR, "ah6_output: unsupported algorithm: "
 		    "SPI=%u\n", (u_int32_t)ntohl(sav->spi)));
-		ipsec6stat.out_inval++;
+		vnet->ipsec6stat.out_inval++;
 		m_freem(m);
 		return EINVAL;
 	}
@@ -467,7 +476,7 @@
 				ipseclog((LOG_WARNING,
 				    "replay counter overflowed. %s\n",
 				    ipsec_logsastr(sav)));
-				ipsec6stat.out_inval++;
+				vnet->ipsec6stat.out_inval++;
 				m_freem(m);
 				return EINVAL;
 			}
@@ -487,13 +496,13 @@
 	 */
 	error = ah6_calccksum(m, (caddr_t)ahsumpos, plen, algo, sav);
 	if (error) {
-		ipsec6stat.out_inval++;
+		vnet->ipsec6stat.out_inval++;
 		m_freem(m);
 	} else {
-		ipsec6stat.out_success++;
+		vnet->ipsec6stat.out_success++;
 		key_sa_recordxfer(sav, m);
 	}
-	ipsec6stat.out_ahhist[sav->alg_auth]++;
+	vnet->ipsec6stat.out_ahhist[sav->alg_auth]++;
 
 	return(error);
 }
diff -urN sys/netinet6/esp.h sys.CORE/netinet6/esp.h
--- sys/netinet6/esp.h	Sat Apr 27 22:40:26 2002
+++ sys.CORE/netinet6/esp.h	Wed Jan 31 16:02:43 2007
@@ -97,7 +97,8 @@
 extern int esp_max_ivlen __P((void));
 
 /* crypt routines */
-extern int esp4_output __P((struct mbuf *, struct ipsecrequest *));
+extern int esp4_output __P((struct mbuf *, struct ipsecrequest *,
+	struct vnet *vnet));
 extern void esp4_input __P((struct mbuf *, ...));
 extern size_t esp_hdrsiz __P((struct ipsecrequest *));
 
diff -urN sys/netinet6/esp6.h sys.CORE/netinet6/esp6.h
--- sys/netinet6/esp6.h	Tue Jul  3 04:01:49 2001
+++ sys.CORE/netinet6/esp6.h	Wed Jan 31 16:02:43 2007
@@ -39,10 +39,10 @@
 
 #ifdef _KERNEL
 extern int esp6_output __P((struct mbuf *, u_char *, struct mbuf *,
-	struct ipsecrequest *));
+	struct ipsecrequest *, struct vnet *));
 extern int esp6_input __P((struct mbuf **, int *, int));
 
-extern void esp6_ctlinput __P((int, struct sockaddr *, void *));
+extern void esp6_ctlinput __P((int, struct sockaddr *, void *, struct vnet *));
 #endif /*_KERNEL*/
 
 #endif /*_NETINET6_ESP6_H_*/
diff -urN sys/netinet6/esp_input.c sys.CORE/netinet6/esp_input.c
--- sys/netinet6/esp_input.c	Fri Nov 28 06:52:52 2003
+++ sys.CORE/netinet6/esp_input.c	Wed Jan 31 16:02:43 2007
@@ -89,6 +89,7 @@
 #include <machine/stdarg.h>
 
 #include <net/net_osdep.h>
+#include <net/vnet.h>
 
 #define IPLEN_FLIPPED
 
@@ -123,17 +124,21 @@
 	int s;
 	va_list ap;
 	int off, proto;
+	struct vnet *vnet;
 
 	va_start(ap, m);
 	off = va_arg(ap, int);
 	proto = va_arg(ap, int);
 	va_end(ap);
 
+	if (m == NULL || m->m_pkthdr.rcvif == NULL)
+		panic("esp4_input: cannot find vnet.");
+	vnet = m->m_pkthdr.rcvif->if_vnet;	
 	/* sanity check for alignment. */
 	if (off % 4 != 0 || m->m_pkthdr.len % 4 != 0) {
 		ipseclog((LOG_ERR, "IPv4 ESP input: packet alignment problem "
 			"(off=%d, pktlen=%d)\n", off, m->m_pkthdr.len));
-		ipsecstat.in_inval++;
+		vnet->ipsecstat.in_inval++;
 		goto bad;
 	}
 
@@ -142,7 +147,7 @@
 		if (!m) {
 			ipseclog((LOG_DEBUG,
 			    "IPv4 ESP input: can't pullup in esp4_input\n"));
-			ipsecstat.in_inval++;
+			vnet->ipsecstat.in_inval++;
 			goto bad;
 		}
 	}
@@ -160,11 +165,11 @@
 
 	if ((sav = key_allocsa(AF_INET,
 	                      (caddr_t)&ip->ip_src, (caddr_t)&ip->ip_dst,
-	                      IPPROTO_ESP, spi)) == 0) {
+	                      IPPROTO_ESP, spi, vnet)) == 0) {
 		ipseclog((LOG_WARNING,
 		    "IPv4 ESP input: no key association found for spi %u\n",
 		    (u_int32_t)ntohl(spi)));
-		ipsecstat.in_nosa++;
+		vnet->ipsecstat.in_nosa++;
 		goto bad;
 	}
 	KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
@@ -174,7 +179,7 @@
 		ipseclog((LOG_DEBUG,
 		    "IPv4 ESP input: non-mature/dying SA found for spi %u\n",
 		    (u_int32_t)ntohl(spi)));
-		ipsecstat.in_badspi++;
+		vnet->ipsecstat.in_badspi++;
 		goto bad;
 	}
 	algo = esp_algorithm_lookup(sav->alg_enc);
@@ -182,7 +187,7 @@
 		ipseclog((LOG_DEBUG, "IPv4 ESP input: "
 		    "unsupported encryption algorithm for spi %u\n",
 		    (u_int32_t)ntohl(spi)));
-		ipsecstat.in_badspi++;
+		vnet->ipsecstat.in_badspi++;
 		goto bad;
 	}
 
@@ -191,7 +196,7 @@
 	if (ivlen < 0) {
 		ipseclog((LOG_ERR, "inproper ivlen in IPv4 ESP input: %s %s\n",
 		    ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav)));
-		ipsecstat.in_inval++;
+		vnet->ipsecstat.in_inval++;
 		goto bad;
 	}
 
@@ -209,7 +214,7 @@
 	if (ipsec_chkreplay(ntohl(((struct newesp *)esp)->esp_seq), sav))
 		; /* okey */
 	else {
-		ipsecstat.in_espreplay++;
+		vnet->ipsecstat.in_espreplay++;
 		ipseclog((LOG_WARNING,
 		    "replay packet in IPv4 ESP input: %s %s\n",
 		    ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav)));
@@ -228,14 +233,14 @@
 		goto noreplaycheck;
 	siz = (((*sumalgo->sumsiz)(sav) + 3) & ~(4 - 1));
 	if (m->m_pkthdr.len < off + ESPMAXLEN + siz) {
-		ipsecstat.in_inval++;
+		vnet->ipsecstat.in_inval++;
 		goto bad;
 	}
 	if (AH_MAXSUMSIZE < siz) {
 		ipseclog((LOG_DEBUG,
 		    "internal error: AH_MAXSUMSIZE must be larger than %lu\n",
 		    (u_long)siz));
-		ipsecstat.in_inval++;
+		vnet->ipsecstat.in_inval++;
 		goto bad;
 	}
 
@@ -244,14 +249,14 @@
 	if (esp_auth(m, off, m->m_pkthdr.len - off - siz, sav, sum)) {
 		ipseclog((LOG_WARNING, "auth fail in IPv4 ESP input: %s %s\n",
 		    ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav)));
-		ipsecstat.in_espauthfail++;
+		vnet->ipsecstat.in_espauthfail++;
 		goto bad;
 	}
 
 	if (bcmp(sum0, sum, siz) != 0) {
 		ipseclog((LOG_WARNING, "auth fail in IPv4 ESP input: %s %s\n",
 		    ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav)));
-		ipsecstat.in_espauthfail++;
+		vnet->ipsecstat.in_espauthfail++;
 		goto bad;
 	}
 
@@ -264,7 +269,7 @@
 	ip->ip_len = htons(ntohs(ip->ip_len) - siz);
 #endif
 	m->m_flags |= M_AUTHIPDGM;
-	ipsecstat.in_espauthsucc++;
+	vnet->ipsecstat.in_espauthsucc++;
     }
 
 	/*
@@ -272,7 +277,7 @@
 	 */
 	if ((sav->flags & SADB_X_EXT_OLD) == 0 && sav->replay) {
 		if (ipsec_updatereplay(ntohl(((struct newesp *)esp)->esp_seq), sav)) {
-			ipsecstat.in_espreplay++;
+			vnet->ipsecstat.in_espreplay++;
 			goto bad;
 		}
 	}
@@ -294,7 +299,7 @@
 	if (m->m_pkthdr.len < off + esplen + ivlen + sizeof(esptail)) {
 		ipseclog((LOG_WARNING,
 		    "IPv4 ESP input: packet too short\n"));
-		ipsecstat.in_inval++;
+		vnet->ipsecstat.in_inval++;
 		goto bad;
 	}
 
@@ -303,7 +308,7 @@
 		if (!m) {
 			ipseclog((LOG_DEBUG,
 			    "IPv4 ESP input: can't pullup in esp4_input\n"));
-			ipsecstat.in_inval++;
+			vnet->ipsecstat.in_inval++;
 			goto bad;
 		}
 	}
@@ -312,7 +317,7 @@
 	 * pre-compute and cache intermediate key
 	 */
 	if (esp_schedule(algo, sav) != 0) {
-		ipsecstat.in_inval++;
+		vnet->ipsecstat.in_inval++;
 		goto bad;
 	}
 
@@ -326,10 +331,10 @@
 		m = NULL;
 		ipseclog((LOG_ERR, "decrypt fail in IPv4 ESP input: %s\n",
 		    ipsec_logsastr(sav)));
-		ipsecstat.in_inval++;
+		vnet->ipsecstat.in_inval++;
 		goto bad;
 	}
-	ipsecstat.in_esphist[sav->alg_enc]++;
+	vnet->ipsecstat.in_esphist[sav->alg_enc]++;
 
 	m->m_flags |= M_DECRYPTED;
 
@@ -346,7 +351,7 @@
 		ipseclog((LOG_WARNING,
 		    "bad pad length in IPv4 ESP input: %s %s\n",
 		    ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav)));
-		ipsecstat.in_inval++;
+		vnet->ipsecstat.in_inval++;
 		goto bad;
 	}
 
@@ -375,36 +380,36 @@
 		if (m->m_len < sizeof(*ip)) {
 			m = m_pullup(m, sizeof(*ip));
 			if (!m) {
-				ipsecstat.in_inval++;
+				vnet->ipsecstat.in_inval++;
 				goto bad;
 			}
 		}
 		ip = mtod(m, struct ip *);
 		/* ECN consideration. */
-		ip_ecn_egress(ip4_ipsec_ecn, &tos, &ip->ip_tos);
+		ip_ecn_egress(vnet->ip4_ipsec_ecn, &tos, &ip->ip_tos);
 		if (!key_checktunnelsanity(sav, AF_INET,
 			    (caddr_t)&ip->ip_src, (caddr_t)&ip->ip_dst)) {
 			ipseclog((LOG_ERR, "ipsec tunnel address mismatch "
 			    "in IPv4 ESP input: %s %s\n",
 			    ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav)));
-			ipsecstat.in_inval++;
+			vnet->ipsecstat.in_inval++;
 			goto bad;
 		}
 
 		key_sa_recordxfer(sav, m);
 		if (ipsec_addhist(m, IPPROTO_ESP, spi) != 0 ||
 		    ipsec_addhist(m, IPPROTO_IPV4, 0) != 0) {
-			ipsecstat.in_nomem++;
+			vnet->ipsecstat.in_nomem++;
 			goto bad;
 		}
 
 		s = splimp();
-		if (IF_QFULL(&ipintrq)) {
-			ipsecstat.in_inval++;
+		if (IF_QFULL(&g_ipintrq)) {
+			vnet->ipsecstat.in_inval++;
 			splx(s);
 			goto bad;
 		}
-		IF_ENQUEUE(&ipintrq, m);
+		IF_ENQUEUE(&g_ipintrq, m);
 		m = NULL;
 		schednetisr(NETISR_IP); /* can be skipped but to make sure */
 		splx(s);
@@ -435,14 +440,14 @@
 
 		key_sa_recordxfer(sav, m);
 		if (ipsec_addhist(m, IPPROTO_ESP, spi) != 0) {
-			ipsecstat.in_nomem++;
+			vnet->ipsecstat.in_nomem++;
 			goto bad;
 		}
 
 		if (nxt != IPPROTO_DONE) {
 			if ((inetsw[ip_protox[nxt]].pr_flags & PR_LASTHDR) != 0 &&
-			    ipsec4_in_reject(m, NULL)) {
-				ipsecstat.in_polvio++;
+			    ipsec4_in_reject(m, NULL, vnet)) {
+				vnet->ipsecstat.in_polvio++;
 				goto bad;
 			}
 			(*inetsw[ip_protox[nxt]].pr_input)(m, off, nxt);
@@ -456,7 +461,7 @@
 			printf("DP esp4_input call free SA:%p\n", sav));
 		key_freesav(sav);
 	}
-	ipsecstat.in_success++;
+	vnet->ipsecstat.in_success++;
 	return;
 
 bad:
@@ -478,6 +483,7 @@
 	int *offp, proto;
 {
 	struct mbuf *m = *mp;
+	struct vnet *vnet;
 	int off = *offp;
 	struct ip6_hdr *ip6;
 	struct esp *esp;
@@ -491,11 +497,14 @@
 	size_t esplen;
 	int s;
 
+	if (m == NULL || m->m_pkthdr.rcvif == NULL)
+		panic("esp6_input: cannot find vnet.");
+	vnet = m->m_pkthdr.rcvif->if_vnet;	
 	/* sanity check for alignment. */
 	if (off % 4 != 0 || m->m_pkthdr.len % 4 != 0) {
 		ipseclog((LOG_ERR, "IPv6 ESP input: packet alignment problem "
 			"(off=%d, pktlen=%d)\n", off, m->m_pkthdr.len));
-		ipsec6stat.in_inval++;
+		vnet->ipsec6stat.in_inval++;
 		goto bad;
 	}
 
@@ -505,7 +514,7 @@
 #else
 	IP6_EXTHDR_GET(esp, struct esp *, m, off, ESPMAXLEN);
 	if (esp == NULL) {
-		ipsec6stat.in_inval++;
+		vnet->ipsec6stat.in_inval++;
 		return IPPROTO_DONE;
 	}
 #endif
@@ -514,7 +523,7 @@
 	if (ntohs(ip6->ip6_plen) == 0) {
 		ipseclog((LOG_ERR, "IPv6 ESP input: "
 		    "ESP with IPv6 jumbogram is not supported.\n"));
-		ipsec6stat.in_inval++;
+		vnet->ipsec6stat.in_inval++;
 		goto bad;
 	}
 
@@ -523,11 +532,11 @@
 
 	if ((sav = key_allocsa(AF_INET6,
 	                      (caddr_t)&ip6->ip6_src, (caddr_t)&ip6->ip6_dst,
-	                      IPPROTO_ESP, spi)) == 0) {
+	                      IPPROTO_ESP, spi, vnet)) == 0) {
 		ipseclog((LOG_WARNING,
 		    "IPv6 ESP input: no key association found for spi %u\n",
 		    (u_int32_t)ntohl(spi)));
-		ipsec6stat.in_nosa++;
+		vnet->ipsec6stat.in_nosa++;
 		goto bad;
 	}
 	KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
@@ -537,7 +546,7 @@
 		ipseclog((LOG_DEBUG,
 		    "IPv6 ESP input: non-mature/dying SA found for spi %u\n",
 		    (u_int32_t)ntohl(spi)));
-		ipsec6stat.in_badspi++;
+		vnet->ipsec6stat.in_badspi++;
 		goto bad;
 	}
 	algo = esp_algorithm_lookup(sav->alg_enc);
@@ -545,7 +554,7 @@
 		ipseclog((LOG_DEBUG, "IPv6 ESP input: "
 		    "unsupported encryption algorithm for spi %u\n",
 		    (u_int32_t)ntohl(spi)));
-		ipsec6stat.in_badspi++;
+		vnet->ipsec6stat.in_badspi++;
 		goto bad;
 	}
 
@@ -554,7 +563,7 @@
 	if (ivlen < 0) {
 		ipseclog((LOG_ERR, "inproper ivlen in IPv6 ESP input: %s %s\n",
 		    ipsec6_logpacketstr(ip6, spi), ipsec_logsastr(sav)));
-		ipsec6stat.in_badspi++;
+		vnet->ipsec6stat.in_badspi++;
 		goto bad;
 	}
 
@@ -572,7 +581,7 @@
 	if (ipsec_chkreplay(ntohl(((struct newesp *)esp)->esp_seq), sav))
 		; /* okey */
 	else {
-		ipsec6stat.in_espreplay++;
+		vnet->ipsec6stat.in_espreplay++;
 		ipseclog((LOG_WARNING,
 		    "replay packet in IPv6 ESP input: %s %s\n",
 		    ipsec6_logpacketstr(ip6, spi), ipsec_logsastr(sav)));
@@ -591,14 +600,14 @@
 		goto noreplaycheck;
 	siz = (((*sumalgo->sumsiz)(sav) + 3) & ~(4 - 1));
 	if (m->m_pkthdr.len < off + ESPMAXLEN + siz) {
-		ipsec6stat.in_inval++;
+		vnet->ipsec6stat.in_inval++;
 		goto bad;
 	}
 	if (AH_MAXSUMSIZE < siz) {
 		ipseclog((LOG_DEBUG,
 		    "internal error: AH_MAXSUMSIZE must be larger than %lu\n",
 		    (u_long)siz));
-		ipsec6stat.in_inval++;
+		vnet->ipsec6stat.in_inval++;
 		goto bad;
 	}
 
@@ -607,14 +616,14 @@
 	if (esp_auth(m, off, m->m_pkthdr.len - off - siz, sav, sum)) {
 		ipseclog((LOG_WARNING, "auth fail in IPv6 ESP input: %s %s\n",
 		    ipsec6_logpacketstr(ip6, spi), ipsec_logsastr(sav)));
-		ipsec6stat.in_espauthfail++;
+		vnet->ipsec6stat.in_espauthfail++;
 		goto bad;
 	}
 
 	if (bcmp(sum0, sum, siz) != 0) {
 		ipseclog((LOG_WARNING, "auth fail in IPv6 ESP input: %s %s\n",
 		    ipsec6_logpacketstr(ip6, spi), ipsec_logsastr(sav)));
-		ipsec6stat.in_espauthfail++;
+		vnet->ipsec6stat.in_espauthfail++;
 		goto bad;
 	}
 
@@ -624,7 +633,7 @@
 	ip6->ip6_plen = htons(ntohs(ip6->ip6_plen) - siz);
 
 	m->m_flags |= M_AUTHIPDGM;
-	ipsec6stat.in_espauthsucc++;
+	vnet->ipsec6stat.in_espauthsucc++;
     }
 
 	/*
@@ -632,7 +641,7 @@
 	 */
 	if ((sav->flags & SADB_X_EXT_OLD) == 0 && sav->replay) {
 		if (ipsec_updatereplay(ntohl(((struct newesp *)esp)->esp_seq), sav)) {
-			ipsec6stat.in_espreplay++;
+			vnet->ipsec6stat.in_espreplay++;
 			goto bad;
 		}
 	}
@@ -654,7 +663,7 @@
 	if (m->m_pkthdr.len < off + esplen + ivlen + sizeof(esptail)) {
 		ipseclog((LOG_WARNING,
 		    "IPv6 ESP input: packet too short\n"));
-		ipsec6stat.in_inval++;
+		vnet->ipsec6stat.in_inval++;
 		goto bad;
 	}
 
@@ -663,7 +672,7 @@
 #else
 	IP6_EXTHDR_GET(esp, struct esp *, m, off, esplen + ivlen);
 	if (esp == NULL) {
-		ipsec6stat.in_inval++;
+		vnet->ipsec6stat.in_inval++;
 		m = NULL;
 		goto bad;
 	}
@@ -674,7 +683,7 @@
 	 * pre-compute and cache intermediate key
 	 */
 	if (esp_schedule(algo, sav) != 0) {
-		ipsec6stat.in_inval++;
+		vnet->ipsec6stat.in_inval++;
 		goto bad;
 	}
 
@@ -688,10 +697,10 @@
 		m = NULL;
 		ipseclog((LOG_ERR, "decrypt fail in IPv6 ESP input: %s\n",
 		    ipsec_logsastr(sav)));
-		ipsec6stat.in_inval++;
+		vnet->ipsec6stat.in_inval++;
 		goto bad;
 	}
-	ipsec6stat.in_esphist[sav->alg_enc]++;
+	vnet->ipsec6stat.in_esphist[sav->alg_enc]++;
 
 	m->m_flags |= M_DECRYPTED;
 
@@ -708,7 +717,7 @@
 		ipseclog((LOG_WARNING,
 		    "bad pad length in IPv6 ESP input: %s %s\n",
 		    ipsec6_logpacketstr(ip6, spi), ipsec_logsastr(sav)));
-		ipsec6stat.in_inval++;
+		vnet->ipsec6stat.in_inval++;
 		goto bad;
 	}
 
@@ -740,37 +749,37 @@
 #endif
 			m = m_pullup(m, sizeof(*ip6));
 			if (!m) {
-				ipsec6stat.in_inval++;
+				vnet->ipsec6stat.in_inval++;
 				goto bad;
 			}
 		}
 		ip6 = mtod(m, struct ip6_hdr *);
 		/* ECN consideration. */
-		ip6_ecn_egress(ip6_ipsec_ecn, &flowinfo, &ip6->ip6_flow);
+		ip6_ecn_egress(vnet->ip6_ipsec_ecn, &flowinfo, &ip6->ip6_flow);
 		if (!key_checktunnelsanity(sav, AF_INET6,
 			    (caddr_t)&ip6->ip6_src, (caddr_t)&ip6->ip6_dst)) {
 			ipseclog((LOG_ERR, "ipsec tunnel address mismatch "
 			    "in IPv6 ESP input: %s %s\n",
 			    ipsec6_logpacketstr(ip6, spi),
 			    ipsec_logsastr(sav)));
-			ipsec6stat.in_inval++;
+			vnet->ipsec6stat.in_inval++;
 			goto bad;
 		}
 
 		key_sa_recordxfer(sav, m);
 		if (ipsec_addhist(m, IPPROTO_ESP, spi) != 0 || 
 		    ipsec_addhist(m, IPPROTO_IPV6, 0) != 0) {
-			ipsec6stat.in_nomem++;
+			vnet->ipsec6stat.in_nomem++;
 			goto bad;
 		}
 
 		s = splimp();
-		if (IF_QFULL(&ip6intrq)) {
-			ipsec6stat.in_inval++;
+		if (IF_QFULL(&g_ip6intrq)) {
+			vnet->ipsec6stat.in_inval++;
 			splx(s);
 			goto bad;
 		}
-		IF_ENQUEUE(&ip6intrq, m);
+		IF_ENQUEUE(&g_ip6intrq, m);
 		m = NULL;
 		schednetisr(NETISR_IPV6); /* can be skipped but to make sure */
 		splx(s);
@@ -864,7 +873,7 @@
 
 		key_sa_recordxfer(sav, m);
 		if (ipsec_addhist(m, IPPROTO_ESP, spi) != 0) {
-			ipsec6stat.in_nomem++;
+			vnet->ipsec6stat.in_nomem++;
 			goto bad;
 		}
 	}
@@ -877,7 +886,7 @@
 			printf("DP esp6_input call free SA:%p\n", sav));
 		key_freesav(sav);
 	}
-	ipsec6stat.in_success++;
+	vnet->ipsec6stat.in_success++;
 	return nxt;
 
 bad:
@@ -892,10 +901,11 @@
 }
 
 void
-esp6_ctlinput(cmd, sa, d)
+esp6_ctlinput(cmd, sa, d, vnet)
 	int cmd;
 	struct sockaddr *sa;
 	void *d;
+	struct vnet *vnet;
 {
 	const struct newesp *espp;
 	struct newesp esp;
@@ -906,6 +916,8 @@
 	int off;
 	struct sockaddr_in6 *sa6_src, *sa6_dst;
 
+	if (vnet == NULL)
+		panic("esp6_ctlinput: NULL vnet was passed.");
 	if (sa->sa_family != AF_INET6 ||
 	    sa->sa_len != sizeof(struct sockaddr_in6))
 		return;
@@ -921,6 +933,7 @@
 	} else {
 		m = NULL;
 		ip6 = NULL;
+		off = 0;
 	}
 
 	if (ip6) {
@@ -939,7 +952,7 @@
 		 */
 		bzero(&ip6cp1, sizeof(ip6cp1));
 		ip6cp1.ip6c_src = ip6cp->ip6c_src;
-		pfctlinput2(cmd, sa, (void *)&ip6cp1);
+		pfctlinput2(cmd, sa, (void *)&ip6cp1, vnet);
 
 		/*
 		 * Then go to special cases that need ESP header information.
@@ -973,7 +986,7 @@
 			sav = key_allocsa(AF_INET6,
 					  (caddr_t)&sa6_src->sin6_addr,
 					  (caddr_t)&sa6_dst->sin6_addr,
-					  IPPROTO_ESP, espp->esp_spi);
+					  IPPROTO_ESP, espp->esp_spi, vnet);
 			if (sav) {
 				if (sav->state == SADB_SASTATE_MATURE ||
 				    sav->state == SADB_SASTATE_DYING)
@@ -990,7 +1003,7 @@
 			 *   corresponding routing entry, or
 			 * - ignore the MTU change notification.
 			 */
-			icmp6_mtudisc_update((struct ip6ctlparam *)d, valid);
+			icmp6_mtudisc_update((struct ip6ctlparam *)d, valid, vnet);
 		}
 	} else {
 		/* we normally notify any pcb here */
diff -urN sys/netinet6/esp_output.c sys.CORE/netinet6/esp_output.c
--- sys/netinet6/esp_output.c	Fri Nov 28 06:54:26 2003
+++ sys.CORE/netinet6/esp_output.c	Wed Jan 31 16:02:43 2007
@@ -78,9 +78,10 @@
 #include <netkey/keydb.h>
 
 #include <net/net_osdep.h>
+#include <net/vnet.h>
 
 static int esp_output __P((struct mbuf *, u_char *, struct mbuf *,
-	struct ipsecrequest *, int));
+	struct ipsecrequest *, int, struct vnet *));
 
 /*
  * compute ESP header size.
@@ -174,12 +175,13 @@
  *	<-----------------> espoff
  */
 static int
-esp_output(m, nexthdrp, md, isr, af)
+esp_output(m, nexthdrp, md, isr, af, vnet)
 	struct mbuf *m;
 	u_char *nexthdrp;
 	struct mbuf *md;
 	struct ipsecrequest *isr;
 	int af;
+	struct vnet *vnet;
 {
 	struct mbuf *n;
 	struct mbuf *mprev;
@@ -197,17 +199,19 @@
 	int error = 0;
 	struct ipsecstat *stat;
 
+	if (vnet == NULL)
+		panic("esp6_output: NULL vnet was passed.");
 	switch (af) {
 #ifdef INET
 	case AF_INET:
 		afnumber = 4;
-		stat = &ipsecstat;
+		stat = &vnet->ipsecstat;
 		break;
 #endif
 #ifdef INET6
 	case AF_INET6:
 		afnumber = 6;
-		stat = &ipsec6stat;
+		stat = &vnet->ipsec6stat;
 		break;
 #endif
 	default:
@@ -229,7 +233,7 @@
 				(u_int32_t)ntohl(ip->ip_src.s_addr),
 				(u_int32_t)ntohl(ip->ip_dst.s_addr),
 				(u_int32_t)ntohl(sav->spi)));
-			ipsecstat.out_inval++;
+			vnet->ipsecstat.out_inval++;
 			break;
 		    }
 #endif /* INET */
@@ -238,7 +242,7 @@
 			ipseclog((LOG_DEBUG, "esp6_output: internal error: "
 				"sav->replay is null: SPI=%u\n",
 				(u_int32_t)ntohl(sav->spi)));
-			ipsec6stat.out_inval++;
+			vnet->ipsec6stat.out_inval++;
 			break;
 #endif /* INET6 */
 		default:
@@ -368,7 +372,7 @@
 		else {
 			ipseclog((LOG_ERR,
 			    "IPv4 ESP output: size exceeds limit\n"));
-			ipsecstat.out_inval++;
+			vnet->ipsecstat.out_inval++;
 			m_freem(m);
 			error = EMSGSIZE;
 			goto fail;
@@ -435,12 +439,12 @@
 	switch (af) {
 #ifdef INET
 	case AF_INET:
-		randpadmax = ip4_esp_randpad;
+		randpadmax = vnet->ip4_esp_randpad;
 		break;
 #endif
 #ifdef INET6
 	case AF_INET6:
-		randpadmax = ip6_esp_randpad;
+		randpadmax = vnet->ip6_esp_randpad;
 		break;
 #endif
 	default:
@@ -539,7 +543,7 @@
 		else {
 			ipseclog((LOG_ERR,
 			    "IPv4 ESP output: size exceeds limit\n"));
-			ipsecstat.out_inval++;
+			vnet->ipsecstat.out_inval++;
 			m_freem(m);
 			error = EMSGSIZE;
 			goto fail;
@@ -651,7 +655,7 @@
 		else {
 			ipseclog((LOG_ERR,
 			    "IPv4 ESP output: size exceeds limit\n"));
-			ipsecstat.out_inval++;
+			vnet->ipsecstat.out_inval++;
 			m_freem(m);
 			error = EMSGSIZE;
 			goto fail;
@@ -686,9 +690,10 @@
 
 #ifdef INET
 int
-esp4_output(m, isr)
+esp4_output(m, isr, vnet)
 	struct mbuf *m;
 	struct ipsecrequest *isr;
+	struct vnet *vnet;
 {
 	struct ip *ip;
 	if (m->m_len < sizeof(struct ip)) {
@@ -698,23 +703,24 @@
 	}
 	ip = mtod(m, struct ip *);
 	/* XXX assumes that m->m_next points to payload */
-	return esp_output(m, &ip->ip_p, m->m_next, isr, AF_INET);
+	return esp_output(m, &ip->ip_p, m->m_next, isr, AF_INET, vnet);
 }
 #endif /* INET */
 
 #ifdef INET6
 int
-esp6_output(m, nexthdrp, md, isr)
+esp6_output(m, nexthdrp, md, isr, vnet)
 	struct mbuf *m;
 	u_char *nexthdrp;
 	struct mbuf *md;
 	struct ipsecrequest *isr;
+	struct vnet *vnet;
 {
 	if (m->m_len < sizeof(struct ip6_hdr)) {
 		ipseclog((LOG_DEBUG, "esp6_output: first mbuf too short\n"));
 		m_freem(m);
 		return 0;
 	}
-	return esp_output(m, nexthdrp, md, isr, AF_INET6);
+	return esp_output(m, nexthdrp, md, isr, AF_INET6, vnet);
 }
 #endif /* INET6 */
diff -urN sys/netinet6/icmp6.c sys.CORE/netinet6/icmp6.c
--- sys/netinet6/icmp6.c	Wed Jan 31 15:57:05 2007
+++ sys.CORE/netinet6/icmp6.c	Wed Jan 31 16:02:43 2007
@@ -2416,7 +2416,7 @@
 	bcopy(&reddst6, &sdst.sin6_addr, sizeof(struct in6_addr));
 	pfctlinput(PRC_REDIRECT_HOST, (struct sockaddr *)&sdst, vnet);
 #ifdef IPSEC
-	key_sa_routechange((struct sockaddr *)&sdst);
+	key_sa_routechange((struct sockaddr *)&sdst, vnet);
 #endif
     }
 
diff -urN sys/netinet6/in6_ifattach.c sys.CORE/netinet6/in6_ifattach.c
--- sys/netinet6/in6_ifattach.c	Wed Jan 31 15:57:05 2007
+++ sys.CORE/netinet6/in6_ifattach.c	Wed Jan 31 16:02:43 2007
@@ -1032,6 +1032,8 @@
 
 	bzero(nullbuf, sizeof(nullbuf));
 	for (i = 1; i < vnet->if_index + 1; i++) {
+		if (vnet->nd_ifinfo == NULL) /* nd6 not initialized yet! */
+			continue;
 		ndi = &vnet->nd_ifinfo[i];
 		if (bcmp(ndi->randomid, nullbuf, sizeof(nullbuf)) != 0) {
 			/*
diff -urN sys/netinet6/in6_proto.c sys.CORE/netinet6/in6_proto.c
--- sys/netinet6/in6_proto.c	Wed Jan 31 15:57:05 2007
+++ sys.CORE/netinet6/in6_proto.c	Wed Jan 31 16:02:43 2007
@@ -209,7 +209,7 @@
 #ifdef IPSEC
 { SOCK_RAW,	&inet6domain,	IPPROTO_AH,	PR_ATOMIC|PR_ADDR,
   ah6_input,	0,		0,		0,
-  0,	
+  0,		0,
   0,		0,		0,		0,
   &nousrreqs,
 },
@@ -218,14 +218,14 @@
   esp6_input,	0,
   esp6_ctlinput,
   0,
-  0,
+  0,		0,
   0,		0,		0,		0,
   &nousrreqs,
 },
 #endif
 { SOCK_RAW,	&inet6domain,	IPPROTO_IPCOMP,	PR_ATOMIC|PR_ADDR,
   ipcomp6_input, 0,	 	0,		0,
-  0,	
+  0,		0,
   0,		0,		0,		0,
   &nousrreqs,
 },
diff -urN sys/netinet6/ip6_forward.c sys.CORE/netinet6/ip6_forward.c
--- sys/netinet6/ip6_forward.c	Wed Jan 31 15:57:05 2007
+++ sys.CORE/netinet6/ip6_forward.c	Wed Jan 31 16:02:43 2007
@@ -122,9 +122,9 @@
 	 * Don't increment ip6s_cantforward because this is the check
 	 * before forwarding packet actually.
 	 */
-	if (ipsec6_in_reject(m, NULL)) {
+	if (ipsec6_in_reject(m, NULL, vnet)) {
 #if !defined(FAST_IPSEC)
-		ipsec6stat.in_polvio++;
+		vnet->ipsec6stat.in_polvio++;
 #endif
 		m_freem(m);
 		return;
@@ -178,9 +178,9 @@
 #ifdef IPSEC
 	/* get a security policy for this packet */
 	sp = ipsec6_getpolicybyaddr(m, IPSEC_DIR_OUTBOUND, IP_FORWARDING,
-	    &error);
+	    &error, vnet);
 	if (sp == NULL) {
-		ipsec6stat.out_inval++;
+		vnet->ipsec6stat.out_inval++;
 		vnet->ip6stat.ip6s_cantforward++;
 		if (mcopy) {
 #if 0
@@ -201,7 +201,7 @@
 		/*
 		 * This packet is just discarded.
 		 */
-		ipsec6stat.out_polvio++;
+		vnet->ipsec6stat.out_polvio++;
 		vnet->ip6stat.ip6s_cantforward++;
 		key_freesp(sp);
 		if (mcopy) {
@@ -263,7 +263,7 @@
 	state.ro = NULL;	/* update at ipsec6_output_tunnel() */
 	state.dst = NULL;	/* update at ipsec6_output_tunnel() */
 
-	error = ipsec6_output_tunnel(&state, sp, 0);
+	error = ipsec6_output_tunnel(&state, sp, 0, vnet);
 
 	m = state.m;
 	key_freesp(sp);
@@ -401,10 +401,10 @@
 			 * encapsulated packet as "rt->rt_ifp".
 			 */
 			sp = ipsec6_getpolicybyaddr(mcopy, IPSEC_DIR_OUTBOUND,
-				IP_FORWARDING, &ipsecerror);
+				IP_FORWARDING, &ipsecerror, vnet);
 			if (sp) {
 				ipsechdrsiz = ipsec6_hdrsiz(mcopy,
-					IPSEC_DIR_OUTBOUND, NULL);
+					IPSEC_DIR_OUTBOUND, NULL, vnet);
 				if (ipsechdrsiz < mtu)
 					mtu -= ipsechdrsiz;
 			}
diff -urN sys/netinet6/ip6_input.c sys.CORE/netinet6/ip6_input.c
--- sys/netinet6/ip6_input.c	Wed Jan 31 15:57:05 2007
+++ sys.CORE/netinet6/ip6_input.c	Wed Jan 31 16:02:43 2007
@@ -928,8 +928,8 @@
 		 * code - like udp/tcp/raw ip.
 		 */
 		if ((inet6sw[ip6_protox[nxt]].pr_flags & PR_LASTHDR) != 0 &&
-		    ipsec6_in_reject(m, NULL)) {
-			ipsec6stat.in_polvio++;
+		    ipsec6_in_reject(m, NULL, vnet)) {
+			vnet->ipsec6stat.in_polvio++;
 			goto bad;
 		}
 #endif
diff -urN sys/netinet6/ip6_output.c sys.CORE/netinet6/ip6_output.c
--- sys/netinet6/ip6_output.c	Wed Jan 31 15:57:05 2007
+++ sys.CORE/netinet6/ip6_output.c	Wed Jan 31 16:02:43 2007
@@ -193,6 +193,8 @@
 	ip6 = mtod(m, struct ip6_hdr *);
 #endif /* FAST_IPSEC */
 
+	if (vnet == NULL)
+		panic("ip6_output: NULL vnet was passed.");
 #define MAKE_EXTHDR(hp, mp)						\
     do {								\
 	if (hp) {							\
@@ -221,12 +223,12 @@
 #ifdef IPSEC
 	/* get a security policy for this packet */
 	if (so == NULL)
-		sp = ipsec6_getpolicybyaddr(m, IPSEC_DIR_OUTBOUND, 0, &error);
+		sp = ipsec6_getpolicybyaddr(m, IPSEC_DIR_OUTBOUND, 0, &error, vnet);
 	else
 		sp = ipsec6_getpolicybysock(m, IPSEC_DIR_OUTBOUND, so, &error);
 
 	if (sp == NULL) {
-		ipsec6stat.out_inval++;
+		vnet->ipsec6stat.out_inval++;
 		goto freehdrs;
 	}
 
@@ -238,7 +240,7 @@
 		/*
 		 * This packet is just discarded.
 		 */
-		ipsec6stat.out_polvio++;
+		vnet->ipsec6stat.out_polvio++;
 		goto freehdrs;
 
 	case IPSEC_POLICY_BYPASS:
@@ -250,7 +252,7 @@
 	case IPSEC_POLICY_IPSEC:
 		if (sp->req == NULL) {
 			/* acquire a policy */
-			error = key_spdacquire(sp);
+			error = key_spdacquire(sp, vnet);
 			goto freehdrs;
 		}
 		needipsec = 1;
@@ -436,7 +438,7 @@
 		bzero(&state, sizeof(state));
 		state.m = m;
 		error = ipsec6_output_trans(&state, nexthdrp, mprev, sp, flags,
-			&needipsectun);
+			&needipsectun, vnet);
 		m = state.m;
 		if (error) {
 			/* mbuf is already reclaimed in ipsec6_output_trans. */
@@ -562,7 +564,7 @@
 		state.ro = (struct route *)ro;
 		state.dst = (struct sockaddr *)dst;
 
-		error = ipsec6_output_tunnel(&state, sp, flags);
+		error = ipsec6_output_tunnel(&state, sp, flags, vnet);
 
 		m = state.m;
 		ro = (struct route_in6 *)state.ro;
@@ -1337,6 +1339,8 @@
 	int alwaysfrag = 0;
 	int error = 0;
 
+	if (vnet == NULL)
+		panic("ip6_getpmtu: NULL vnet was passed.");
 	if (ro_pmtu != ro) {
 		/* The first hop and the final destination may differ. */
 		struct sockaddr_in6 *sa6_dst =
@@ -1416,6 +1420,8 @@
 	int optlen;
 	struct proc *p;
 
+	if (vnet == NULL)
+		panic("ip6_ctloutput: NULL vnet from socket.");
 	if (sopt) {
 		level = sopt->sopt_level;
 		op = sopt->sopt_dir;
@@ -1853,6 +1859,8 @@
 	struct proc *p = sopt->sopt_p;
 	int priv = 0;
 
+	if (vnet == NULL)
+		panic("ip6_pcbopts: NULL vnet from socket.");
 	/* turn off any old options. */
 	if (opt) {
 #ifdef DIAGNOSTIC
@@ -2042,6 +2050,8 @@
 	struct in6_multi_mship *imm;
 	struct proc *p = curproc;	/* XXX */
 
+	if (vnet == NULL)
+		panic("ip6_setmoptions: NULL vnet passed.");
 	if (im6o == NULL) {
 		/*
 		 * No multicast option buffer attached to the pcb;
@@ -2326,6 +2336,8 @@
 
 	*mp = m_get(M_WAIT, MT_HEADER);		/* XXX */
 
+	if (vnet == NULL)
+		panic("ip6_getmoptions: NULL vnet was passed.");
 	switch (optname) {
 
 	case IPV6_MULTICAST_IF:
diff -urN sys/netinet6/ipcomp_input.c sys.CORE/netinet6/ipcomp_input.c
--- sys/netinet6/ipcomp_input.c	Sat Apr 27 22:40:27 2002
+++ sys.CORE/netinet6/ipcomp_input.c	Wed Jan 31 16:02:43 2007
@@ -47,6 +47,7 @@
 #include <sys/time.h>
 #include <sys/syslog.h>
 
+/*#include <net/vnet.h>*/
 #include <net/if.h>
 #include <net/route.h>
 #include <net/netisr.h>
@@ -79,6 +80,7 @@
 #include <machine/stdarg.h>
 
 #include <net/net_osdep.h>
+#include <net/vnet.h>
 
 #define IPLEN_FLIPPED
 
@@ -106,6 +108,7 @@
 	size_t newlen, olen;
 	struct secasvar *sav = NULL;
 	int off, proto;
+	struct vnet *vnet;
 	va_list ap;
 
 	va_start(ap, m);
@@ -113,10 +116,14 @@
 	proto = va_arg(ap, int);
 	va_end(ap);
 
+	if (m == NULL || m->m_pkthdr.rcvif == NULL)
+		panic("ipcomp_input: cannot find vnet.");
+	vnet = m->m_pkthdr.rcvif->if_vnet;
+	
 	if (m->m_pkthdr.len < off + sizeof(struct ipcomp)) {
 		ipseclog((LOG_DEBUG, "IPv4 IPComp input: assumption failed "
 		    "(packet too short)\n"));
-		ipsecstat.in_inval++;
+		vnet->ipsecstat.in_inval++;
 		goto fail;
 	}
 
@@ -125,7 +132,7 @@
 		m = NULL;	/* already freed */
 		ipseclog((LOG_DEBUG, "IPv4 IPComp input: assumption failed "
 		    "(pulldown failure)\n"));
-		ipsecstat.in_inval++;
+		vnet->ipsecstat.in_inval++;
 		goto fail;
 	}
 	ipcomp = mtod(md, struct ipcomp *);
@@ -141,7 +148,7 @@
 
 	if (cpi >= IPCOMP_CPI_NEGOTIATE_MIN) {
 		sav = key_allocsa(AF_INET, (caddr_t)&ip->ip_src,
-			(caddr_t)&ip->ip_dst, IPPROTO_IPCOMP, htonl(cpi));
+			(caddr_t)&ip->ip_dst, IPPROTO_IPCOMP, htonl(cpi), vnet);
 		if (sav != NULL
 		 && (sav->state == SADB_SASTATE_MATURE
 		  || sav->state == SADB_SASTATE_DYING)) {
@@ -153,7 +160,7 @@
 	if (!algo) {
 		ipseclog((LOG_WARNING, "IPv4 IPComp input: unknown cpi %u\n",
 			cpi));
-		ipsecstat.in_nosa++;
+		vnet->ipsecstat.in_nosa++;
 		goto fail;
 	}
 
@@ -173,13 +180,13 @@
 	error = (*algo->decompress)(m, m->m_next, &newlen);
 	if (error != 0) {
 		if (error == EINVAL)
-			ipsecstat.in_inval++;
+			vnet->ipsecstat.in_inval++;
 		else if (error == ENOBUFS)
-			ipsecstat.in_nomem++;
+			vnet->ipsecstat.in_nomem++;
 		m = NULL;
 		goto fail;
 	}
-	ipsecstat.in_comphist[cpi]++;
+	vnet->ipsecstat.in_comphist[cpi]++;
 
 	/*
 	 * returning decompressed packet onto icmp is meaningless.
@@ -204,7 +211,7 @@
 	len -= olen;
 	if (len & ~0xffff) {
 		/* packet too big after decompress */
-		ipsecstat.in_inval++;
+		vnet->ipsecstat.in_inval++;
 		goto fail;
 	}
 #ifdef IPLEN_FLIPPED
@@ -218,7 +225,7 @@
 	if (sav) {
 		key_sa_recordxfer(sav, m);
 		if (ipsec_addhist(m, IPPROTO_IPCOMP, (u_int32_t)cpi) != 0) {
-			ipsecstat.in_nomem++;
+			vnet->ipsecstat.in_nomem++;
 			goto fail;
 		}
 		key_freesav(sav);
@@ -227,8 +234,8 @@
 
 	if (nxt != IPPROTO_DONE) {
 		if ((inetsw[ip_protox[nxt]].pr_flags & PR_LASTHDR) != 0 &&
-		    ipsec4_in_reject(m, NULL)) {
-			ipsecstat.in_polvio++;
+		    ipsec4_in_reject(m, NULL, vnet)) {
+			vnet->ipsecstat.in_polvio++;
 			goto fail;
 		}
 		(*inetsw[ip_protox[nxt]].pr_input)(m, off, nxt);
@@ -236,7 +243,7 @@
 		m_freem(m);
 	m = NULL;
 
-	ipsecstat.in_success++;
+	vnet->ipsecstat.in_success++;
 	return;
 
 fail:
@@ -265,16 +272,20 @@
 	size_t newlen;
 	struct secasvar *sav = NULL;
 	char *prvnxtp;
+	struct vnet *vnet = NULL;
 
 	m = *mp;
 	off = *offp;
 
+	if (m == NULL || m->m_pkthdr.rcvif == NULL)
+		panic("ipcomp6_input: unable to find vnet.");
+	vnet = m->m_pkthdr.rcvif->if_vnet;
 	md = m_pulldown(m, off, sizeof(*ipcomp), NULL);
 	if (!m) {
 		m = NULL;	/* already freed */
 		ipseclog((LOG_DEBUG, "IPv6 IPComp input: assumption failed "
 		    "(pulldown failure)\n"));
-		ipsec6stat.in_inval++;
+		vnet->ipsec6stat.in_inval++;
 		goto fail;
 	}
 	ipcomp = mtod(md, struct ipcomp *);
@@ -285,7 +296,8 @@
 
 	if (cpi >= IPCOMP_CPI_NEGOTIATE_MIN) {
 		sav = key_allocsa(AF_INET6, (caddr_t)&ip6->ip6_src,
-			(caddr_t)&ip6->ip6_dst, IPPROTO_IPCOMP, htonl(cpi));
+			(caddr_t)&ip6->ip6_dst, IPPROTO_IPCOMP, htonl(cpi),
+			vnet);
 		if (sav != NULL
 		 && (sav->state == SADB_SASTATE_MATURE
 		  || sav->state == SADB_SASTATE_DYING)) {
@@ -297,7 +309,7 @@
 	if (!algo) {
 		ipseclog((LOG_WARNING, "IPv6 IPComp input: unknown cpi %u; "
 			"dropping the packet for simplicity\n", cpi));
-		ipsec6stat.in_nosa++;
+		vnet->ipsec6stat.in_nosa++;
 		goto fail;
 	}
 
@@ -311,13 +323,13 @@
 	error = (*algo->decompress)(m, md, &newlen);
 	if (error != 0) {
 		if (error == EINVAL)
-			ipsec6stat.in_inval++;
+			vnet->ipsec6stat.in_inval++;
 		else if (error == ENOBUFS)
-			ipsec6stat.in_nomem++;
+			vnet->ipsec6stat.in_nomem++;
 		m = NULL;
 		goto fail;
 	}
-	ipsec6stat.in_comphist[cpi]++;
+	vnet->ipsec6stat.in_comphist[cpi]++;
 	m->m_pkthdr.len = off + newlen;
 
 	/*
@@ -338,7 +350,7 @@
 	if (sav) {
 		key_sa_recordxfer(sav, m);
 		if (ipsec_addhist(m, IPPROTO_IPCOMP, (u_int32_t)cpi) != 0) {
-			ipsec6stat.in_nomem++;
+			vnet->ipsec6stat.in_nomem++;
 			goto fail;
 		}
 		key_freesav(sav);
@@ -346,7 +358,7 @@
 	}
 	*offp = off;
 	*mp = m;
-	ipsec6stat.in_success++;
+	vnet->ipsec6stat.in_success++;
 	return nxt;
 
 fail:
diff -urN sys/netinet6/ipcomp_output.c sys.CORE/netinet6/ipcomp_output.c
--- sys/netinet6/ipcomp_output.c	Tue Apr 29 01:33:50 2003
+++ sys.CORE/netinet6/ipcomp_output.c	Wed Jan 31 16:02:43 2007
@@ -80,6 +80,7 @@
 #include <machine/stdarg.h>
 
 #include <net/net_osdep.h>
+#include <net/vnet.h>
 
 static int ipcomp_output __P((struct mbuf *, u_char *, struct mbuf *,
 	struct ipsecrequest *, int));
@@ -123,18 +124,23 @@
 	int afnumber;
 	int error = 0;
 	struct ipsecstat *stat;
+	struct vnet *vnet;
+
+	if (m == NULL || m->m_pkthdr.rcvif == NULL)
+		panic("ipcomp_output: unable to get vnet.");
+	vnet = m->m_pkthdr.rcvif->if_vnet;
 
 	switch (af) {
 #ifdef INET
 	case AF_INET:
 		afnumber = 4;
-		stat = &ipsecstat;
+		stat = &vnet->ipsecstat;
 		break;
 #endif
 #ifdef INET6
 	case AF_INET6:
 		afnumber = 6;
-		stat = &ipsec6stat;
+		stat = &vnet->ipsec6stat;
 		break;
 #endif
 	default:
@@ -309,7 +315,7 @@
 		else {
 			ipseclog((LOG_ERR,
 			    "IPv4 ESP output: size exceeds limit\n"));
-			ipsecstat.out_inval++;
+			vnet->ipsecstat.out_inval++;
 			m_freem(m);
 			error = EMSGSIZE;
 			goto fail;
@@ -353,9 +359,14 @@
 	struct ipsecrequest *isr;
 {
 	struct ip *ip;
+	struct vnet *vnet;
+
+	if (m == NULL || m->m_pkthdr.rcvif == NULL)
+		panic("ipcomp4_output: unable to get vnet.");
+	vnet = m->m_pkthdr.rcvif->if_vnet;
 	if (m->m_len < sizeof(struct ip)) {
 		ipseclog((LOG_DEBUG, "ipcomp4_output: first mbuf too short\n"));
-		ipsecstat.out_inval++;
+		vnet->ipsecstat.out_inval++;
 		m_freem(m);
 		return 0;
 	}
@@ -373,9 +384,13 @@
 	struct mbuf *md;
 	struct ipsecrequest *isr;
 {
+	struct vnet *vnet;
+	if (m == NULL || m->m_pkthdr.rcvif == NULL)
+		panic("ipcomp6_output: cannot find vnet.");
+	vnet = m->m_pkthdr.rcvif->if_vnet;	
 	if (m->m_len < sizeof(struct ip6_hdr)) {
 		ipseclog((LOG_DEBUG, "ipcomp6_output: first mbuf too short\n"));
-		ipsec6stat.out_inval++;
+		vnet->ipsec6stat.out_inval++;
 		m_freem(m);
 		return 0;
 	}
diff -urN sys/netinet6/ipsec.c sys.CORE/netinet6/ipsec.c
--- sys/netinet6/ipsec.c	Wed Jan 31 15:57:05 2007
+++ sys.CORE/netinet6/ipsec.c	Wed Jan 31 16:02:43 2007
@@ -112,6 +112,7 @@
 int ipsec_debug = 0;
 #endif
 
+#ifdef MOVED_TO_VNET
 struct ipsecstat ipsecstat;
 int ip4_ah_cleartos = 1;
 int ip4_ah_offsetmask = 0;	/* maybe IP_DF? */
@@ -123,6 +124,7 @@
 struct secpolicy ip4_def_policy;
 int ip4_ipsec_ecn = 0;		/* ECN ignore(-1)/forbidden(0)/allowed(1) */
 int ip4_esp_randpad = -1;
+#endif
 
 #ifdef SYSCTL_DECL
 SYSCTL_DECL(_net_inet_ipsec);
@@ -132,32 +134,33 @@
 #endif
 
 /* net.inet.ipsec */
-SYSCTL_STRUCT(_net_inet_ipsec, IPSECCTL_STATS,
-	stats, CTLFLAG_RD,	&ipsecstat,	ipsecstat, "");
-SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEF_POLICY,
-	def_policy, CTLFLAG_RW,	&ip4_def_policy.policy,	0, "");
-SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEF_ESP_TRANSLEV, esp_trans_deflev,
-	CTLFLAG_RW, &ip4_esp_trans_deflev,	0, "");
-SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEF_ESP_NETLEV, esp_net_deflev,
-	CTLFLAG_RW, &ip4_esp_net_deflev,	0, "");
-SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEF_AH_TRANSLEV, ah_trans_deflev,
-	CTLFLAG_RW, &ip4_ah_trans_deflev,	0, "");
-SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEF_AH_NETLEV, ah_net_deflev,
-	CTLFLAG_RW, &ip4_ah_net_deflev,	0, "");
-SYSCTL_INT(_net_inet_ipsec, IPSECCTL_AH_CLEARTOS,
-	ah_cleartos, CTLFLAG_RW,	&ip4_ah_cleartos,	0, "");
-SYSCTL_INT(_net_inet_ipsec, IPSECCTL_AH_OFFSETMASK,
-	ah_offsetmask, CTLFLAG_RW,	&ip4_ah_offsetmask,	0, "");
-SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DFBIT,
-	dfbit, CTLFLAG_RW,	&ip4_ipsec_dfbit,	0, "");
-SYSCTL_INT(_net_inet_ipsec, IPSECCTL_ECN,
-	ecn, CTLFLAG_RW,	&ip4_ipsec_ecn,	0, "");
+SYSCTL_V_STRUCT(V_NET, _net_inet_ipsec, IPSECCTL_STATS,
+	stats, CTLFLAG_RD,	v_ipsecstat,	ipsecstat, "");
+SYSCTL_V_INT(V_NET, _net_inet_ipsec, IPSECCTL_DEF_POLICY,
+	def_policy, CTLFLAG_RW,	&((struct secpolicy*)v_ip4_def_policy)->policy,	0, "");
+SYSCTL_V_INT(V_NET, _net_inet_ipsec, IPSECCTL_DEF_ESP_TRANSLEV,
+	esp_trans_deflev, CTLFLAG_RW, v_ip4_esp_trans_deflev,	0, "");
+SYSCTL_V_INT(V_NET, _net_inet_ipsec, IPSECCTL_DEF_ESP_NETLEV, esp_net_deflev,
+	CTLFLAG_RW, v_ip4_esp_net_deflev,	0, "");
+SYSCTL_V_INT(V_NET, _net_inet_ipsec, IPSECCTL_DEF_AH_TRANSLEV, ah_trans_deflev,
+	CTLFLAG_RW, v_ip4_ah_trans_deflev,	0, "");
+SYSCTL_V_INT(V_NET, _net_inet_ipsec, IPSECCTL_DEF_AH_NETLEV, ah_net_deflev,
+	CTLFLAG_RW, v_ip4_ah_net_deflev,	0, "");
+SYSCTL_V_INT(V_NET, _net_inet_ipsec, IPSECCTL_AH_CLEARTOS,
+	ah_cleartos, CTLFLAG_RW,	v_ip4_ah_cleartos,	0, "");
+SYSCTL_V_INT(V_NET, _net_inet_ipsec, IPSECCTL_AH_OFFSETMASK,
+	ah_offsetmask, CTLFLAG_RW,	v_ip4_ah_offsetmask,	0, "");
+SYSCTL_V_INT(V_NET, _net_inet_ipsec, IPSECCTL_DFBIT,
+	dfbit, CTLFLAG_RW,	v_ip4_ipsec_dfbit,	0, "");
+SYSCTL_V_INT(V_NET, _net_inet_ipsec, IPSECCTL_ECN,
+	ecn, CTLFLAG_RW,	v_ip4_ipsec_ecn,	0, "");
 SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEBUG,
 	debug, CTLFLAG_RW,	&ipsec_debug,	0, "");
-SYSCTL_INT(_net_inet_ipsec, IPSECCTL_ESP_RANDPAD,
-	esp_randpad, CTLFLAG_RW,	&ip4_esp_randpad,	0, "");
+SYSCTL_V_INT(V_NET, _net_inet_ipsec, IPSECCTL_ESP_RANDPAD,
+	esp_randpad, CTLFLAG_RW,	v_ip4_esp_randpad,	0, "");
 
 #ifdef INET6
+#ifdef MOVED_TO_VNET
 struct ipsecstat ipsec6stat;
 int ip6_esp_trans_deflev = IPSEC_LEVEL_USE;
 int ip6_esp_net_deflev = IPSEC_LEVEL_USE;
@@ -166,26 +169,27 @@
 struct secpolicy ip6_def_policy;
 int ip6_ipsec_ecn = 0;		/* ECN ignore(-1)/forbidden(0)/allowed(1) */
 int ip6_esp_randpad = -1;
+#endif /* MOVED_TO_VNET */
 
 /* net.inet6.ipsec6 */
-SYSCTL_STRUCT(_net_inet6_ipsec6, IPSECCTL_STATS,
-	stats, CTLFLAG_RD, &ipsec6stat, ipsecstat, "");
-SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEF_POLICY,
-	def_policy, CTLFLAG_RW,	&ip6_def_policy.policy,	0, "");
-SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEF_ESP_TRANSLEV, esp_trans_deflev,
-	CTLFLAG_RW, &ip6_esp_trans_deflev,	0, "");
-SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEF_ESP_NETLEV, esp_net_deflev,
-	CTLFLAG_RW, &ip6_esp_net_deflev,	0, "");
-SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEF_AH_TRANSLEV, ah_trans_deflev,
-	CTLFLAG_RW, &ip6_ah_trans_deflev,	0, "");
-SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEF_AH_NETLEV, ah_net_deflev,
-	CTLFLAG_RW, &ip6_ah_net_deflev,	0, "");
-SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_ECN,
-	ecn, CTLFLAG_RW,	&ip6_ipsec_ecn,	0, "");
+SYSCTL_V_STRUCT(V_NET, _net_inet6_ipsec6, IPSECCTL_STATS,
+	stats, CTLFLAG_RD, v_ipsec6stat, ipsecstat, "");
+SYSCTL_V_INT(V_NET, _net_inet6_ipsec6, IPSECCTL_DEF_POLICY,
+	def_policy, CTLFLAG_RW,	&((struct secpolicy *)v_ip6_def_policy)->policy, 0, "");
+SYSCTL_V_INT(V_NET, _net_inet6_ipsec6, IPSECCTL_DEF_ESP_TRANSLEV,
+	esp_trans_deflev, CTLFLAG_RW, v_ip6_esp_trans_deflev,	0, "");
+SYSCTL_V_INT(V_NET, _net_inet6_ipsec6, IPSECCTL_DEF_ESP_NETLEV, esp_net_deflev,
+	CTLFLAG_RW, v_ip6_esp_net_deflev,	0, "");
+SYSCTL_V_INT(V_NET, _net_inet6_ipsec6, IPSECCTL_DEF_AH_TRANSLEV,
+	ah_trans_deflev, CTLFLAG_RW, v_ip6_ah_trans_deflev,	0, "");
+SYSCTL_V_INT(V_NET, _net_inet6_ipsec6, IPSECCTL_DEF_AH_NETLEV, ah_net_deflev,
+	CTLFLAG_RW, v_ip6_ah_net_deflev,	0, "");
+SYSCTL_V_INT(V_NET, _net_inet6_ipsec6, IPSECCTL_ECN,
+	ecn, CTLFLAG_RW,	v_ip6_ipsec_ecn,	0, "");
 SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEBUG,
 	debug, CTLFLAG_RW,	&ipsec_debug,	0, "");
-SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_ESP_RANDPAD,
-	esp_randpad, CTLFLAG_RW,	&ip6_esp_randpad,	0, "");
+SYSCTL_V_INT(V_NET, _net_inet6_ipsec6, IPSECCTL_ESP_RANDPAD,
+	esp_randpad, CTLFLAG_RW,	v_ip6_esp_randpad,	0, "");
 #endif /* INET6 */
 
 static int ipsec_setspidx_mbuf
@@ -217,10 +221,10 @@
 static struct mbuf *ipsec6_splithdr __P((struct mbuf *));
 #endif
 #ifdef INET
-static int ipsec4_encapsulate __P((struct mbuf *, struct secasvar *));
+static int ipsec4_encapsulate __P((struct mbuf *, struct secasvar *, struct vnet *));
 #endif
 #ifdef INET6
-static int ipsec6_encapsulate __P((struct mbuf *, struct secasvar *));
+static int ipsec6_encapsulate __P((struct mbuf *, struct secasvar *, struct vnet *));
 #endif
 
 /*
@@ -245,11 +249,15 @@
 	struct inpcbpolicy *pcbsp = NULL;
 	struct secpolicy *currsp = NULL;	/* policy on socket */
 	struct secpolicy *kernsp = NULL;	/* policy on kernel */
+	struct vnet *vnet;
 
 	/* sanity check */
 	if (m == NULL || so == NULL || error == NULL)
 		panic("ipsec4_getpolicybysock: NULL pointer was passed.");
-
+	vnet = so->so_vnet;
+	if (vnet == NULL)
+		panic("ipsec4_getpolicybysock: NULL vnet pointer.");
+	
 	switch (so->so_proto->pr_domain->dom_family) {
 	case AF_INET:
 		/* set spidx in pcb */
@@ -306,7 +314,7 @@
 
 		case IPSEC_POLICY_ENTRUST:
 			/* look for a policy in SPD */
-			kernsp = key_allocsp(&currsp->spidx, dir);
+			kernsp = key_allocsp(&currsp->spidx, dir, vnet);
 
 			/* SP found */
 			if (kernsp != NULL) {
@@ -318,16 +326,16 @@
 			}
 
 			/* no SP found */
-			if (ip4_def_policy.policy != IPSEC_POLICY_DISCARD
-			 && ip4_def_policy.policy != IPSEC_POLICY_NONE) {
+			if (vnet->ip4_def_policy.policy != IPSEC_POLICY_DISCARD
+			 && vnet->ip4_def_policy.policy != IPSEC_POLICY_NONE) {
 				ipseclog((LOG_INFO,
 				    "fixed system default policy: %d->%d\n",
-				    ip4_def_policy.policy, IPSEC_POLICY_NONE));
-				ip4_def_policy.policy = IPSEC_POLICY_NONE;
+				    vnet->ip4_def_policy.policy, IPSEC_POLICY_NONE));
+				vnet->ip4_def_policy.policy = IPSEC_POLICY_NONE;
 			}
-			ip4_def_policy.refcnt++;
+			vnet->ip4_def_policy.refcnt++;
 			*error = 0;
-			return &ip4_def_policy;
+			return &vnet->ip4_def_policy;
 			
 		case IPSEC_POLICY_IPSEC:
 			currsp->refcnt++;
@@ -345,7 +353,7 @@
 
 	/* when non-privilieged socket */
 	/* look for a policy in SPD */
-	kernsp = key_allocsp(&currsp->spidx, dir);
+	kernsp = key_allocsp(&currsp->spidx, dir, vnet);
 
 	/* SP found */
 	if (kernsp != NULL) {
@@ -366,16 +374,16 @@
 		return NULL;
 
 	case IPSEC_POLICY_ENTRUST:
-		if (ip4_def_policy.policy != IPSEC_POLICY_DISCARD
-		 && ip4_def_policy.policy != IPSEC_POLICY_NONE) {
+		if (vnet->ip4_def_policy.policy != IPSEC_POLICY_DISCARD
+		 && vnet->ip4_def_policy.policy != IPSEC_POLICY_NONE) {
 			ipseclog((LOG_INFO,
 			    "fixed system default policy: %d->%d\n",
-			    ip4_def_policy.policy, IPSEC_POLICY_NONE));
-			ip4_def_policy.policy = IPSEC_POLICY_NONE;
+			    vnet->ip4_def_policy.policy, IPSEC_POLICY_NONE));
+			vnet->ip4_def_policy.policy = IPSEC_POLICY_NONE;
 		}
-		ip4_def_policy.refcnt++;
+		vnet->ip4_def_policy.refcnt++;
 		*error = 0;
-		return &ip4_def_policy;
+		return &vnet->ip4_def_policy;
 
 	case IPSEC_POLICY_IPSEC:
 		currsp->refcnt++;
@@ -402,17 +410,20 @@
  *		others	: error occured.
  */
 struct secpolicy *
-ipsec4_getpolicybyaddr(m, dir, flag, error)
+ipsec4_getpolicybyaddr(m, dir, flag, error, vnet)
 	struct mbuf *m;
 	u_int dir;
 	int flag;
 	int *error;
+	struct vnet *vnet;
 {
 	struct secpolicy *sp = NULL;
 
 	/* sanity check */
 	if (m == NULL || error == NULL)
 		panic("ipsec4_getpolicybyaddr: NULL pointer was passed.");
+	if (vnet == NULL)
+		panic("ipsec4_getpolicybyaddr: NULL vnet pointer was passed.");
 
     {
 	struct secpolicyindex spidx;
@@ -426,7 +437,7 @@
 	if (*error != 0)
 		return NULL;
 
-	sp = key_allocsp(&spidx, dir);
+	sp = key_allocsp(&spidx, dir, vnet);
     }
 
 	/* SP found */
@@ -439,16 +450,16 @@
 	}
 
 	/* no SP found */
-	if (ip4_def_policy.policy != IPSEC_POLICY_DISCARD
-	 && ip4_def_policy.policy != IPSEC_POLICY_NONE) {
+	if (vnet->ip4_def_policy.policy != IPSEC_POLICY_DISCARD
+	 && vnet->ip4_def_policy.policy != IPSEC_POLICY_NONE) {
 		ipseclog((LOG_INFO, "fixed system default policy:%d->%d\n",
-			ip4_def_policy.policy,
+			vnet->ip4_def_policy.policy,
 			IPSEC_POLICY_NONE));
-		ip4_def_policy.policy = IPSEC_POLICY_NONE;
+		vnet->ip4_def_policy.policy = IPSEC_POLICY_NONE;
 	}
-	ip4_def_policy.refcnt++;
+	vnet->ip4_def_policy.refcnt++;
 	*error = 0;
-	return &ip4_def_policy;
+	return &vnet->ip4_def_policy;
 }
 
 #ifdef INET6
@@ -472,10 +483,15 @@
 	struct inpcbpolicy *pcbsp = NULL;
 	struct secpolicy *currsp = NULL;	/* policy on socket */
 	struct secpolicy *kernsp = NULL;	/* policy on kernel */
+	struct vnet *vnet;
 
 	/* sanity check */
 	if (m == NULL || so == NULL || error == NULL)
 		panic("ipsec6_getpolicybysock: NULL pointer was passed.");
+	vnet = so->so_vnet;
+	if (vnet == NULL)
+		panic("ipsec6_getpolicybysock: NULL vnet pointer was passed.");
+	
 
 #ifdef DIAGNOSTIC
 	if (so->so_proto->pr_domain->dom_family != AF_INET6)
@@ -516,7 +532,7 @@
 
 		case IPSEC_POLICY_ENTRUST:
 			/* look for a policy in SPD */
-			kernsp = key_allocsp(&currsp->spidx, dir);
+			kernsp = key_allocsp(&currsp->spidx, dir, vnet);
 
 			/* SP found */
 			if (kernsp != NULL) {
@@ -528,16 +544,16 @@
 			}
 
 			/* no SP found */
-			if (ip6_def_policy.policy != IPSEC_POLICY_DISCARD
-			 && ip6_def_policy.policy != IPSEC_POLICY_NONE) {
+			if (vnet->ip6_def_policy.policy != IPSEC_POLICY_DISCARD
+			 && vnet->ip6_def_policy.policy != IPSEC_POLICY_NONE) {
 				ipseclog((LOG_INFO,
 				    "fixed system default policy: %d->%d\n",
-				    ip6_def_policy.policy, IPSEC_POLICY_NONE));
-				ip6_def_policy.policy = IPSEC_POLICY_NONE;
+				    vnet->ip6_def_policy.policy, IPSEC_POLICY_NONE));
+				vnet->ip6_def_policy.policy = IPSEC_POLICY_NONE;
 			}
-			ip6_def_policy.refcnt++;
+			vnet->ip6_def_policy.refcnt++;
 			*error = 0;
-			return &ip6_def_policy;
+			return &vnet->ip6_def_policy;
 			
 		case IPSEC_POLICY_IPSEC:
 			currsp->refcnt++;
@@ -555,7 +571,7 @@
 
 	/* when non-privilieged socket */
 	/* look for a policy in SPD */
-	kernsp = key_allocsp(&currsp->spidx, dir);
+	kernsp = key_allocsp(&currsp->spidx, dir, vnet);
 
 	/* SP found */
 	if (kernsp != NULL) {
@@ -576,16 +592,16 @@
 		return NULL;
 
 	case IPSEC_POLICY_ENTRUST:
-		if (ip6_def_policy.policy != IPSEC_POLICY_DISCARD
-		 && ip6_def_policy.policy != IPSEC_POLICY_NONE) {
+		if (vnet->ip6_def_policy.policy != IPSEC_POLICY_DISCARD
+		 && vnet->ip6_def_policy.policy != IPSEC_POLICY_NONE) {
 			ipseclog((LOG_INFO,
 			    "fixed system default policy: %d->%d\n",
-			    ip6_def_policy.policy, IPSEC_POLICY_NONE));
-			ip6_def_policy.policy = IPSEC_POLICY_NONE;
+			    vnet->ip6_def_policy.policy, IPSEC_POLICY_NONE));
+			vnet->ip6_def_policy.policy = IPSEC_POLICY_NONE;
 		}
-		ip6_def_policy.refcnt++;
+		vnet->ip6_def_policy.refcnt++;
 		*error = 0;
-		return &ip6_def_policy;
+		return &vnet->ip6_def_policy;
 
 	case IPSEC_POLICY_IPSEC:
 		currsp->refcnt++;
@@ -619,17 +635,20 @@
 #endif
 
 struct secpolicy *
-ipsec6_getpolicybyaddr(m, dir, flag, error)
+ipsec6_getpolicybyaddr(m, dir, flag, error, vnet)
 	struct mbuf *m;
 	u_int dir;
 	int flag;
 	int *error;
+	struct vnet *vnet;
 {
 	struct secpolicy *sp = NULL;
 
 	/* sanity check */
 	if (m == NULL || error == NULL)
 		panic("ipsec6_getpolicybyaddr: NULL pointer was passed.");
+	if (vnet == NULL)
+		panic("ipsec6_getpolicybyaddr: NULL vnet pointer was passed.");
 
     {
 	struct secpolicyindex spidx;
@@ -643,7 +662,7 @@
 	if (*error != 0)
 		return NULL;
 
-	sp = key_allocsp(&spidx, dir);
+	sp = key_allocsp(&spidx, dir, vnet);
     }
 
 	/* SP found */
@@ -656,15 +675,15 @@
 	}
 
 	/* no SP found */
-	if (ip6_def_policy.policy != IPSEC_POLICY_DISCARD
-	 && ip6_def_policy.policy != IPSEC_POLICY_NONE) {
+	if (vnet->ip6_def_policy.policy != IPSEC_POLICY_DISCARD
+	 && vnet->ip6_def_policy.policy != IPSEC_POLICY_NONE) {
 		ipseclog((LOG_INFO, "fixed system default policy: %d->%d\n",
-		    ip6_def_policy.policy, IPSEC_POLICY_NONE));
-		ip6_def_policy.policy = IPSEC_POLICY_NONE;
+		    vnet->ip6_def_policy.policy, IPSEC_POLICY_NONE));
+		vnet->ip6_def_policy.policy = IPSEC_POLICY_NONE;
 	}
-	ip6_def_policy.refcnt++;
+	vnet->ip6_def_policy.refcnt++;
 	*error = 0;
-	return &ip6_def_policy;
+	return &vnet->ip6_def_policy;
 }
 #endif /* INET6 */
 
@@ -1505,8 +1524,9 @@
  * Either IPSEC_LEVEL_USE or IPSEC_LEVEL_REQUIRE are always returned.
  */
 u_int
-ipsec_get_reqlevel(isr)
+ipsec_get_reqlevel(isr, vnet)
 	struct ipsecrequest *isr;
+	struct vnet *vnet;
 {
 	u_int level = 0;
 	u_int esp_trans_deflev, esp_net_deflev, ah_trans_deflev, ah_net_deflev;
@@ -1514,6 +1534,8 @@
 	/* sanity check */
 	if (isr == NULL || isr->sp == NULL)
 		panic("ipsec_get_reqlevel: NULL pointer is passed.");
+	if (vnet == NULL)
+		panic("ipsec_get_reqlevel: NULL vnet is passed.");
 	if (((struct sockaddr *)&isr->sp->spidx.src)->sa_family
 			!= ((struct sockaddr *)&isr->sp->spidx.dst)->sa_family)
 		panic("ipsec_get_reqlevel: family mismatched.");
@@ -1534,18 +1556,18 @@
 	switch (((struct sockaddr *)&isr->sp->spidx.src)->sa_family) {
 #ifdef INET
 	case AF_INET:
-		esp_trans_deflev = IPSEC_CHECK_DEFAULT(ip4_esp_trans_deflev);
-		esp_net_deflev = IPSEC_CHECK_DEFAULT(ip4_esp_net_deflev);
-		ah_trans_deflev = IPSEC_CHECK_DEFAULT(ip4_ah_trans_deflev);
-		ah_net_deflev = IPSEC_CHECK_DEFAULT(ip4_ah_net_deflev);
+		esp_trans_deflev = IPSEC_CHECK_DEFAULT(vnet->ip4_esp_trans_deflev);
+		esp_net_deflev = IPSEC_CHECK_DEFAULT(vnet->ip4_esp_net_deflev);
+		ah_trans_deflev = IPSEC_CHECK_DEFAULT(vnet->ip4_ah_trans_deflev);
+		ah_net_deflev = IPSEC_CHECK_DEFAULT(vnet->ip4_ah_net_deflev);
 		break;
 #endif
 #ifdef INET6
 	case AF_INET6:
-		esp_trans_deflev = IPSEC_CHECK_DEFAULT(ip6_esp_trans_deflev);
-		esp_net_deflev = IPSEC_CHECK_DEFAULT(ip6_esp_net_deflev);
-		ah_trans_deflev = IPSEC_CHECK_DEFAULT(ip6_ah_trans_deflev);
-		ah_net_deflev = IPSEC_CHECK_DEFAULT(ip6_ah_net_deflev);
+		esp_trans_deflev = IPSEC_CHECK_DEFAULT(vnet->ip6_esp_trans_deflev);
+		esp_net_deflev = IPSEC_CHECK_DEFAULT(vnet->ip6_esp_net_deflev);
+		ah_trans_deflev = IPSEC_CHECK_DEFAULT(vnet->ip6_ah_trans_deflev);
+		ah_net_deflev = IPSEC_CHECK_DEFAULT(vnet->ip6_ah_net_deflev);
 		break;
 #endif /* INET6 */
 	default:
@@ -1614,10 +1636,16 @@
 	struct ipsecrequest *isr;
 	u_int level;
 	int need_auth, need_conf, need_icv;
+	struct vnet *vnet;
 
 	KEYDEBUG(KEYDEBUG_IPSEC_DATA,
 		printf("ipsec_in_reject: using SP\n");
 		kdebug_secpolicy(sp));
+	if (m == NULL || m->m_pkthdr.rcvif == NULL)
+		panic("ipsec_in_reject(): unable to get vnet.");
+	vnet = m->m_pkthdr.rcvif->if_vnet;
+	if (vnet == NULL)
+		panic("ipsec_in_reject(): NULL vnet was passed.");
 
 	/* check policy */
 	switch (sp->policy) {
@@ -1644,7 +1672,7 @@
 	for (isr = sp->req; isr != NULL; isr = isr->next) {
 
 		/* get current level */
-		level = ipsec_get_reqlevel(isr);
+		level = ipsec_get_reqlevel(isr, vnet);
 
 		switch (isr->saidx.proto) {
 		case IPPROTO_ESP:
@@ -1691,9 +1719,10 @@
  * and {ah,esp}4_input for tunnel mode
  */
 int
-ipsec4_in_reject_so(m, so)
+ipsec4_in_reject_so(m, so, vnet)
 	struct mbuf *m;
 	struct socket *so;
+	struct vnet *vnet;
 {
 	struct secpolicy *sp = NULL;
 	int error;
@@ -1708,7 +1737,7 @@
 	 * ipsec4_getpolicybyaddr() with IP_FORWARDING flag.
 	 */
 	if (so == NULL)
-		sp = ipsec4_getpolicybyaddr(m, IPSEC_DIR_INBOUND, IP_FORWARDING, &error);
+		sp = ipsec4_getpolicybyaddr(m, IPSEC_DIR_INBOUND, IP_FORWARDING, &error, vnet);
 	else
 		sp = ipsec4_getpolicybysock(m, IPSEC_DIR_INBOUND, so, &error);
 
@@ -1725,14 +1754,15 @@
 }
 
 int
-ipsec4_in_reject(m, inp)
+ipsec4_in_reject(m, inp, vnet)
 	struct mbuf *m;
 	struct inpcb *inp;
+	struct vnet *vnet;
 {
 	if (inp == NULL)
-		return ipsec4_in_reject_so(m, NULL);
+		return ipsec4_in_reject_so(m, NULL, vnet);
 	if (inp->inp_socket)
-		return ipsec4_in_reject_so(m, inp->inp_socket);
+		return ipsec4_in_reject_so(m, inp->inp_socket, vnet);
 	else
 		panic("ipsec4_in_reject: invalid inpcb/socket");
 }
@@ -1744,9 +1774,10 @@
  * and {ah,esp}6_input for tunnel mode
  */
 int
-ipsec6_in_reject_so(m, so)
+ipsec6_in_reject_so(m, so, vnet)
 	struct mbuf *m;
 	struct socket *so;
+	struct vnet *vnet;
 {
 	struct secpolicy *sp = NULL;
 	int error;
@@ -1761,7 +1792,7 @@
 	 * ipsec6_getpolicybyaddr() with IP_FORWARDING flag.
 	 */
 	if (so == NULL)
-		sp = ipsec6_getpolicybyaddr(m, IPSEC_DIR_INBOUND, IP_FORWARDING, &error);
+		sp = ipsec6_getpolicybyaddr(m, IPSEC_DIR_INBOUND, IP_FORWARDING, &error, vnet);
 	else
 		sp = ipsec6_getpolicybysock(m, IPSEC_DIR_INBOUND, so, &error);
 
@@ -1777,14 +1808,15 @@
 }
 
 int
-ipsec6_in_reject(m, in6p)
+ipsec6_in_reject(m, in6p, vnet)
 	struct mbuf *m;
 	struct in6pcb *in6p;
+	struct vnet *vnet;
 {
 	if (in6p == NULL)
-		return ipsec6_in_reject_so(m, NULL);
+		return ipsec6_in_reject_so(m, NULL, vnet);
 	if (in6p->in6p_socket)
-		return ipsec6_in_reject_so(m, in6p->in6p_socket);
+		return ipsec6_in_reject_so(m, in6p->in6p_socket, vnet);
 	else
 		panic("ipsec6_in_reject: invalid in6p/socket");
 }
@@ -1868,10 +1900,11 @@
 
 /* This function is called from ip_forward() and ipsec4_hdrsize_tcp(). */
 size_t
-ipsec4_hdrsiz(m, dir, inp)
+ipsec4_hdrsiz(m, dir, inp, vnet)
 	struct mbuf *m;
 	u_int dir;
 	struct inpcb *inp;
+	struct vnet *vnet;
 {
 	struct secpolicy *sp = NULL;
 	int error;
@@ -1888,7 +1921,7 @@
 	 * ipsec4_getpolicybyaddr() with IP_FORWARDING flag.
 	 */
 	if (inp == NULL)
-		sp = ipsec4_getpolicybyaddr(m, dir, IP_FORWARDING, &error);
+		sp = ipsec4_getpolicybyaddr(m, dir, IP_FORWARDING, &error,vnet);
 	else
 		sp = ipsec4_getpolicybysock(m, dir, inp->inp_socket, &error);
 
@@ -1910,10 +1943,11 @@
  * and maybe from ip6_forward.()
  */
 size_t
-ipsec6_hdrsiz(m, dir, in6p)
+ipsec6_hdrsiz(m, dir, in6p, vnet)
 	struct mbuf *m;
 	u_int dir;
 	struct in6pcb *in6p;
+	struct vnet *vnet;
 {
 	struct secpolicy *sp = NULL;
 	int error;
@@ -1928,7 +1962,7 @@
 	/* get SP for this packet */
 	/* XXX Is it right to call with IP_FORWARDING. */
 	if (in6p == NULL)
-		sp = ipsec6_getpolicybyaddr(m, dir, IP_FORWARDING, &error);
+		sp = ipsec6_getpolicybyaddr(m, dir, IP_FORWARDING, &error, vnet);
 	else
 		sp = ipsec6_getpolicybysock(m, dir, in6p->in6p_socket, &error);
 
@@ -1951,9 +1985,10 @@
  * ip->ip_src must be fixed later on.
  */
 static int
-ipsec4_encapsulate(m, sav)
+ipsec4_encapsulate(m, sav, vnet)
 	struct mbuf *m;
 	struct secasvar *sav;
+	struct vnet *vnet;
 {
 	struct ip *oip;
 	struct ip *ip;
@@ -1967,6 +2002,8 @@
 		m_freem(m);
 		return EINVAL;
 	}
+	if (vnet == NULL)
+		panic("ipsec4_encapsulate(): vnet is NULL.");
 #if 0
 	/* XXX if the dst is myself, perform nothing. */
 	if (key_ismyaddr((struct sockaddr *)&sav->sah->saidx.dst)) {
@@ -2030,7 +2067,7 @@
 
 	/* construct new IPv4 header. see RFC 2401 5.1.2.1 */
 	/* ECN consideration. */
-	ip_ecn_ingress(ip4_ipsec_ecn, &ip->ip_tos, &oip->ip_tos);
+	ip_ecn_ingress(vnet->ip4_ipsec_ecn, &ip->ip_tos, &oip->ip_tos);
 #ifdef _IP_VHL
 	ip->ip_vhl = IP_MAKE_VHL(IPVERSION, sizeof(struct ip) >> 2);
 #else
@@ -2038,7 +2075,7 @@
 #endif
 	ip->ip_off &= htons(~IP_OFFMASK);
 	ip->ip_off &= htons(~IP_MF);
-	switch (ip4_ipsec_dfbit) {
+	switch (vnet->ip4_ipsec_dfbit) {
 	case 0:	/* clear DF bit */
 		ip->ip_off &= htons(~IP_DF);
 		break;
@@ -2058,7 +2095,7 @@
 #ifdef RANDOM_IP_ID
 	ip->ip_id = ip_randomid();
 #else
-	ip->ip_id = htons(ip_id++);
+	ip->ip_id = htons(vnet->ip_id++);
 #endif
 	bcopy(&((struct sockaddr_in *)&sav->sah->saidx.src)->sin_addr,
 		&ip->ip_src, sizeof(ip->ip_src));
@@ -2074,14 +2111,18 @@
 
 #ifdef INET6
 static int
-ipsec6_encapsulate(m, sav)
+ipsec6_encapsulate(m, sav, vnet)
 	struct mbuf *m;
 	struct secasvar *sav;
+	struct vnet *vnet;
 {
 	struct ip6_hdr *oip6;
 	struct ip6_hdr *ip6;
 	size_t plen;
 
+	if (vnet == NULL)
+		panic("ipsec6_encapsulate(): vnet is NULL.");
+
 	/* can't tunnel between different AFs */
 	if (((struct sockaddr *)&sav->sah->saidx.src)->sa_family
 		!= ((struct sockaddr *)&sav->sah->saidx.dst)->sa_family
@@ -2133,7 +2174,7 @@
 
 	/* construct new IPv6 header. see RFC 2401 5.1.2.2 */
 	/* ECN consideration. */
-	ip6_ecn_ingress(ip6_ipsec_ecn, &ip6->ip6_flow, &oip6->ip6_flow);
+	ip6_ecn_ingress(vnet->ip6_ipsec_ecn, &ip6->ip6_flow, &oip6->ip6_flow);
 	if (plen < IPV6_MAXPACKET - sizeof(struct ip6_hdr))
 		ip6->ip6_plen = htons(plen);
 	else {
@@ -2493,6 +2534,8 @@
 		panic("state->ro == NULL in ipsec4_output");
 	if (!state->dst)
 		panic("state->dst == NULL in ipsec4_output");
+	if (vnet == NULL)
+		panic("ipsec4_output: vnet is NULL.");
 
 	KEYDEBUG(KEYDEBUG_IPSEC_DATA,
 		printf("ipsec4_output: applyed SP\n");
@@ -2541,13 +2584,13 @@
 			 * this packet because it is responsibility for
 			 * upper layer to retransmit the packet.
 			 */
-			ipsecstat.out_nosa++;
+			vnet->ipsecstat.out_nosa++;
 			goto bad;
 		}
 
 		/* validity check */
 		if (isr->sav == NULL) {
-			switch (ipsec_get_reqlevel(isr)) {
+			switch (ipsec_get_reqlevel(isr, vnet)) {
 			case IPSEC_LEVEL_USE:
 				continue;
 			case IPSEC_LEVEL_REQUIRE:
@@ -2565,7 +2608,7 @@
 		 */
 		if (isr->sav->state != SADB_SASTATE_MATURE
 		 && isr->sav->state != SADB_SASTATE_DYING) {
-			ipsecstat.out_nosa++;
+			vnet->ipsecstat.out_nosa++;
 			error = EINVAL;
 			goto bad;
 		}
@@ -2596,7 +2639,7 @@
 				error = ENOMEM;
 				goto bad;
 			}
-			error = ipsec4_encapsulate(state->m, isr->sav);
+			error = ipsec4_encapsulate(state->m, isr->sav, vnet);
 			splx(s);
 			if (error) {
 				state->m = NULL;
@@ -2641,7 +2684,7 @@
 		switch (isr->saidx.proto) {
 		case IPPROTO_ESP:
 #ifdef IPSEC_ESP
-			if ((error = esp4_output(state->m, isr)) != 0) {
+			if ((error = esp4_output(state->m, isr, vnet)) != 0) {
 				state->m = NULL;
 				goto bad;
 			}
@@ -2653,7 +2696,7 @@
 			goto bad;
 #endif
 		case IPPROTO_AH:
-			if ((error = ah4_output(state->m, isr)) != 0) {
+			if ((error = ah4_output(state->m, isr, vnet)) != 0) {
 				state->m = NULL;
 				goto bad;
 			}
@@ -2695,13 +2738,14 @@
  * IPsec output logic for IPv6, transport mode.
  */
 int
-ipsec6_output_trans(state, nexthdrp, mprev, sp, flags, tun)
+ipsec6_output_trans(state, nexthdrp, mprev, sp, flags, tun, vnet)
 	struct ipsec_output_state *state;
 	u_char *nexthdrp;
 	struct mbuf *mprev;
 	struct secpolicy *sp;
 	int flags;
 	int *tun;
+	struct vnet *vnet;
 {
 	struct ip6_hdr *ip6;
 	struct ipsecrequest *isr = NULL;
@@ -2722,6 +2766,8 @@
 		panic("sp == NULL in ipsec6_output_trans");
 	if (!tun)
 		panic("tun == NULL in ipsec6_output_trans");
+	if (!vnet)
+		panic("vnet == NULL in ipsec6_output_trans");
 
 	KEYDEBUG(KEYDEBUG_IPSEC_DATA,
 		printf("ipsec6_output_trans: applyed SP\n");
@@ -2766,7 +2812,7 @@
 			}
 		}
 
-		if (key_checkrequest(isr, &saidx) == ENOENT) {
+		if (key_checkrequest(isr, &saidx, vnet) == ENOENT) {
 			/*
 			 * IPsec processing is required, but no SA found.
 			 * I assume that key_acquire() had been called
@@ -2774,7 +2820,7 @@
 			 * this packet because it is responsibility for
 			 * upper layer to retransmit the packet.
 			 */
-			ipsec6stat.out_nosa++;
+			vnet->ipsec6stat.out_nosa++;
 			error = ENOENT;
 
 			/*
@@ -2793,7 +2839,7 @@
 
 		/* validity check */
 		if (isr->sav == NULL) {
-			switch (ipsec_get_reqlevel(isr)) {
+			switch (ipsec_get_reqlevel(isr, vnet)) {
 			case IPSEC_LEVEL_USE:
 				continue;
 			case IPSEC_LEVEL_REQUIRE:
@@ -2808,7 +2854,7 @@
 		 */
 		if (isr->sav->state != SADB_SASTATE_MATURE
 		 && isr->sav->state != SADB_SASTATE_DYING) {
-			ipsec6stat.out_nosa++;
+			vnet->ipsec6stat.out_nosa++;
 			error = EINVAL;
 			goto bad;
 		}
@@ -2816,7 +2862,7 @@
 		switch (isr->saidx.proto) {
 		case IPPROTO_ESP:
 #ifdef IPSEC_ESP
-			error = esp6_output(state->m, nexthdrp, mprev->m_next, isr);
+			error = esp6_output(state->m, nexthdrp, mprev->m_next, isr, vnet);
 #else
 			m_freem(state->m);
 			error = EINVAL;
@@ -2832,7 +2878,7 @@
 			ipseclog((LOG_ERR, "ipsec6_output_trans: "
 			    "unknown ipsec protocol %d\n", isr->saidx.proto));
 			m_freem(state->m);
-			ipsec6stat.out_inval++;
+			vnet->ipsec6stat.out_inval++;
 			error = EINVAL;
 			break;
 		}
@@ -2844,7 +2890,7 @@
 		if (plen > IPV6_MAXPACKET) {
 			ipseclog((LOG_ERR, "ipsec6_output_trans: "
 			    "IPsec with IPv6 jumbogram is not supported\n"));
-			ipsec6stat.out_inval++;
+			vnet->ipsec6stat.out_inval++;
 			error = EINVAL;	/* XXX */
 			goto bad;
 		}
@@ -2868,10 +2914,11 @@
  * IPsec output logic for IPv6, tunnel mode.
  */
 int
-ipsec6_output_tunnel(state, sp, flags)
+ipsec6_output_tunnel(state, sp, flags, vnet)
 	struct ipsec_output_state *state;
 	struct secpolicy *sp;
 	int flags;
+	struct vnet *vnet;
 {
 	struct ip6_hdr *ip6;
 	struct ipsecrequest *isr = NULL;
@@ -2887,6 +2934,8 @@
 		panic("state->m == NULL in ipsec6_output_tunnel");
 	if (!sp)
 		panic("sp == NULL in ipsec6_output_tunnel");
+	if (!vnet)
+		panic("vnet == NULL in ipsec6_output_tunnel");
 
 	KEYDEBUG(KEYDEBUG_IPSEC_DATA,
 		printf("ipsec6_output_tunnel: applyed SP\n");
@@ -2943,7 +2992,7 @@
 			}
 		}
 
-		if (key_checkrequest(isr, &saidx) == ENOENT) {
+		if (key_checkrequest(isr, &saidx, vnet) == ENOENT) {
 			/*
 			 * IPsec processing is required, but no SA found.
 			 * I assume that key_acquire() had been called
@@ -2951,14 +3000,14 @@
 			 * this packet because it is responsibility for
 			 * upper layer to retransmit the packet.
 			 */
-			ipsec6stat.out_nosa++;
+			vnet->ipsec6stat.out_nosa++;
 			error = ENOENT;
 			goto bad;
 		}
 
 		/* validity check */
 		if (isr->sav == NULL) {
-			switch (ipsec_get_reqlevel(isr)) {
+			switch (ipsec_get_reqlevel(isr, vnet)) {
 			case IPSEC_LEVEL_USE:
 				continue;
 			case IPSEC_LEVEL_REQUIRE:
@@ -2973,7 +3022,7 @@
 		 */
 		if (isr->sav->state != SADB_SASTATE_MATURE
 		 && isr->sav->state != SADB_SASTATE_DYING) {
-			ipsec6stat.out_nosa++;
+			vnet->ipsec6stat.out_nosa++;
 			error = EINVAL;
 			goto bad;
 		}
@@ -2994,7 +3043,7 @@
 				    "family mismatched between inner and outer, spi=%u\n",
 				    (u_int32_t)ntohl(isr->sav->spi)));
 				splx(s);
-				ipsec6stat.out_inval++;
+				vnet->ipsec6stat.out_inval++;
 				error = EAFNOSUPPORT;
 				goto bad;
 			}
@@ -3002,11 +3051,11 @@
 			state->m = ipsec6_splithdr(state->m);
 			if (!state->m) {
 				splx(s);
-				ipsec6stat.out_nomem++;
+				vnet->ipsec6stat.out_nomem++;
 				error = ENOMEM;
 				goto bad;
 			}
-			error = ipsec6_encapsulate(state->m, isr->sav);
+			error = ipsec6_encapsulate(state->m, isr->sav, vnet);
 			splx(s);
 			if (error) {
 				state->m = 0;
@@ -3028,11 +3077,11 @@
 				dst6->sin6_family = AF_INET6;
 				dst6->sin6_len = sizeof(*dst6);
 				dst6->sin6_addr = ip6->ip6_dst;
-				rtalloc(state->ro);
+				rtalloc(state->ro, vnet);
 			}
 			if (state->ro->ro_rt == 0) {
-				ip6stat.ip6s_noroute++;
-				ipsec6stat.out_noroute++;
+				vnet->ip6stat.ip6s_noroute++;
+				vnet->ipsec6stat.out_noroute++;
 				error = EHOSTUNREACH;
 				goto bad;
 			}
@@ -3047,7 +3096,7 @@
 
 		state->m = ipsec6_splithdr(state->m);
 		if (!state->m) {
-			ipsec6stat.out_nomem++;
+			vnet->ipsec6stat.out_nomem++;
 			error = ENOMEM;
 			goto bad;
 		}
@@ -3055,7 +3104,7 @@
 		switch (isr->saidx.proto) {
 		case IPPROTO_ESP:
 #ifdef IPSEC_ESP
-			error = esp6_output(state->m, &ip6->ip6_nxt, state->m->m_next, isr);
+			error = esp6_output(state->m, &ip6->ip6_nxt, state->m->m_next, isr, vnet);
 #else
 			m_freem(state->m);
 			error = EINVAL;
@@ -3071,7 +3120,7 @@
 			ipseclog((LOG_ERR, "ipsec6_output_tunnel: "
 			    "unknown ipsec protocol %d\n", isr->saidx.proto));
 			m_freem(state->m);
-			ipsec6stat.out_inval++;
+			vnet->ipsec6stat.out_inval++;
 			error = EINVAL;
 			break;
 		}
@@ -3083,7 +3132,7 @@
 		if (plen > IPV6_MAXPACKET) {
 			ipseclog((LOG_ERR, "ipsec6_output_tunnel: "
 			    "IPsec with IPv6 jumbogram is not supported\n"));
-			ipsec6stat.out_inval++;
+			vnet->ipsec6stat.out_inval++;
 			error = EINVAL;	/* XXX */
 			goto bad;
 		}
@@ -3193,7 +3242,11 @@
 	int hlen;
 	struct secpolicy *sp;
 	struct ip *oip;
+	struct vnet *vnet;
 
+	if (m == NULL || m->m_pkthdr.rcvif == NULL)
+		panic("ipsec4_tunnel_validate: cannot find vnet.");
+	vnet = m->m_pkthdr.rcvif->if_vnet;
 #ifdef DIAGNOSTIC
 	if (m->m_len < sizeof(struct ip))
 		panic("too short mbuf on ipsec4_tunnel_validate");
@@ -3260,7 +3313,7 @@
 	 */
 
 	sp = key_gettunnel((struct sockaddr *)&osrc, (struct sockaddr *)&odst,
-	    (struct sockaddr *)&isrc, (struct sockaddr *)&idst);
+	    (struct sockaddr *)&isrc, (struct sockaddr *)&idst, vnet);
 	if (!sp)
 		return 0;
 	key_freesp(sp);
@@ -3282,7 +3335,12 @@
 	struct sockaddr_in6 osrc, odst, isrc, idst;
 	struct secpolicy *sp;
 	struct ip6_hdr *oip6;
+	struct vnet *vnet;
 
+	if (m == NULL || m->m_pkthdr.rcvif == NULL)
+		panic("ipsec6_tunnel_validate: cannot find vnet.");
+	vnet = m->m_pkthdr.rcvif->if_vnet;
+	
 #ifdef DIAGNOSTIC
 	if (m->m_len < sizeof(struct ip6_hdr))
 		panic("too short mbuf on ipsec6_tunnel_validate");
@@ -3325,7 +3383,7 @@
 	 */
 
 	sp = key_gettunnel((struct sockaddr *)&osrc, (struct sockaddr *)&odst,
-	    (struct sockaddr *)&isrc, (struct sockaddr *)&idst);
+	    (struct sockaddr *)&isrc, (struct sockaddr *)&idst, vnet);
 	/*
 	 * when there is no suitable inbound policy for the packet of the ipsec
 	 * tunnel mode, the kernel never decapsulate the tunneled packet
diff -urN sys/netinet6/ipsec.h sys.CORE/netinet6/ipsec.h
--- sys/netinet6/ipsec.h	Wed Jan 31 15:57:05 2007
+++ sys.CORE/netinet6/ipsec.h	Wed Jan 31 16:02:43 2007
@@ -285,6 +285,7 @@
 
 extern int ipsec_debug;
 
+#ifdef MOVED_TO_VNET
 extern struct ipsecstat ipsecstat;
 extern struct secpolicy ip4_def_policy;
 extern int ip4_esp_trans_deflev;
@@ -296,34 +297,36 @@
 extern int ip4_ipsec_dfbit;
 extern int ip4_ipsec_ecn;
 extern int ip4_esp_randpad;
+#endif
 
 #define ipseclog(x)	do { if (ipsec_debug) log x; } while (0)
 
 extern struct secpolicy *ipsec4_getpolicybysock
 	__P((struct mbuf *, u_int, struct socket *, int *));
 extern struct secpolicy *ipsec4_getpolicybyaddr
-	__P((struct mbuf *, u_int, int, int *));
+	__P((struct mbuf *, u_int, int, int *, struct vnet *));
 
 struct inpcb;
 extern int ipsec_init_policy __P((struct socket *so, struct inpcbpolicy **));
 extern int ipsec_copy_policy
 	__P((struct inpcbpolicy *, struct inpcbpolicy *));
-extern u_int ipsec_get_reqlevel __P((struct ipsecrequest *));
+extern u_int ipsec_get_reqlevel __P((struct ipsecrequest *, struct vnet *));
 
 extern int ipsec4_set_policy __P((struct inpcb *inp, int optname,
 	caddr_t request, size_t len, int priv));
 extern int ipsec4_get_policy __P((struct inpcb *inpcb, caddr_t request,
 	size_t len, struct mbuf **mp));
 extern int ipsec4_delete_pcbpolicy __P((struct inpcb *));
-extern int ipsec4_in_reject_so __P((struct mbuf *, struct socket *));
-extern int ipsec4_in_reject __P((struct mbuf *, struct inpcb *));
+extern int ipsec4_in_reject_so __P((struct mbuf *, struct socket *, struct vnet *));
+extern int ipsec4_in_reject __P((struct mbuf *, struct inpcb *, struct vnet *));
 
 struct secas;
 struct tcpcb;
 extern int ipsec_chkreplay __P((u_int32_t, struct secasvar *));
 extern int ipsec_updatereplay __P((u_int32_t, struct secasvar *));
 
-extern size_t ipsec4_hdrsiz __P((struct mbuf *, u_int, struct inpcb *));
+extern size_t ipsec4_hdrsiz __P((struct mbuf *, u_int, struct inpcb *,
+	struct vnet *));
 extern size_t ipsec_hdrsiz_tcp __P((struct tcpcb *));
 
 struct ip;
diff -urN sys/netinet6/ipsec6.h sys.CORE/netinet6/ipsec6.h
--- sys/netinet6/ipsec6.h	Tue Jul  3 04:01:54 2001
+++ sys.CORE/netinet6/ipsec6.h	Wed Jan 31 16:02:43 2007
@@ -53,29 +53,29 @@
 extern struct secpolicy *ipsec6_getpolicybysock
 	__P((struct mbuf *, u_int, struct socket *, int *));
 extern struct secpolicy *ipsec6_getpolicybyaddr
-	__P((struct mbuf *, u_int, int, int *));
+	__P((struct mbuf *, u_int, int, int *, struct vnet *));
 
 struct inpcb;
 
-extern int ipsec6_in_reject_so __P((struct mbuf *, struct socket *));
+extern int ipsec6_in_reject_so __P((struct mbuf *, struct socket *, struct vnet *));
 extern int ipsec6_delete_pcbpolicy __P((struct inpcb *));
 extern int ipsec6_set_policy __P((struct inpcb *inp, int optname,
 	caddr_t request, size_t len, int priv));
 extern int ipsec6_get_policy
 	__P((struct inpcb *inp, caddr_t request, size_t len, struct mbuf **mp));
-extern int ipsec6_in_reject __P((struct mbuf *, struct inpcb *));
+extern int ipsec6_in_reject __P((struct mbuf *, struct inpcb *, struct vnet *));
 
 struct tcp6cb;
 
-extern size_t ipsec6_hdrsiz __P((struct mbuf *, u_int, struct inpcb *));
+extern size_t ipsec6_hdrsiz __P((struct mbuf *, u_int, struct inpcb *, struct vnet *vnet));
 
 struct ip6_hdr;
 extern const char *ipsec6_logpacketstr __P((struct ip6_hdr *, u_int32_t));
 
 extern int ipsec6_output_trans __P((struct ipsec_output_state *, u_char *,
-	struct mbuf *, struct secpolicy *, int, int *));
+	struct mbuf *, struct secpolicy *, int, int *, struct vnet *));
 extern int ipsec6_output_tunnel __P((struct ipsec_output_state *,
-	struct secpolicy *, int));
+	struct secpolicy *, int, struct vnet *));
 extern int ipsec6_tunnel_validate __P((struct mbuf *, int, u_int,
 	struct secasvar *));
 #endif /*_KERNEL*/
diff -urN sys/netinet6/raw_ip6.c sys.CORE/netinet6/raw_ip6.c
--- sys/netinet6/raw_ip6.c	Wed Jan 31 15:57:05 2007
+++ sys.CORE/netinet6/raw_ip6.c	Wed Jan 31 16:02:43 2007
@@ -168,9 +168,9 @@
 			/*
 			 * Check AH/ESP integrity.
 			 */
-			if (n && ipsec6_in_reject_so(n, last->inp_socket)) {
+			if (n && ipsec6_in_reject_so(n, last->inp_socket, vnet)) {
 				m_freem(n);
-				ipsec6stat.in_polvio++;
+				vnet->ipsec6stat.in_polvio++;
 				/* do not inject data into pcb */
 			} else
 #endif /*IPSEC*/
@@ -207,10 +207,10 @@
 	/*
 	 * Check AH/ESP integrity.
 	 */
-	if (last && ipsec6_in_reject_so(m, last->inp_socket)) {
+	if (last && ipsec6_in_reject_so(m, last->inp_socket, vnet)) {
 		m_freem(m);
-		ipsec6stat.in_polvio++;
-		ip6stat.ip6s_delivered--;
+		vnet->ipsec6stat.in_polvio++;
+		vnet->ip6stat.ip6s_delivered--;
 		/* do not inject data into pcb */
 	} else
 #endif /*IPSEC*/
@@ -220,7 +220,7 @@
 	 */
 	if (last && ipsec6_in_reject(m, last)) {
 		m_freem(m);
-		ip6stat.ip6s_delivered--;
+		vnet->ip6stat.ip6s_delivered--;
 		/* do not inject data into pcb */
 	} else
 #endif /*FAST_IPSEC*/
diff -urN sys/netinet6/udp6_usrreq.c sys.CORE/netinet6/udp6_usrreq.c
--- sys/netinet6/udp6_usrreq.c	Wed Jan 31 15:57:05 2007
+++ sys.CORE/netinet6/udp6_usrreq.c	Wed Jan 31 16:02:43 2007
@@ -260,8 +260,8 @@
 				/*
 				 * Check AH/ESP integrity.
 				 */
-				if (ipsec6_in_reject_so(m, last->inp_socket))
-					ipsec6stat.in_polvio++;
+				if (ipsec6_in_reject_so(m, last->inp_socket, vnet))
+					vnet->ipsec6stat.in_polvio++;
 					/* do not inject data into pcb */
 				else
 #endif /* IPSEC */
@@ -327,8 +327,8 @@
 		/*
 		 * Check AH/ESP integrity.
 		 */
-		if (ipsec6_in_reject_so(m, last->inp_socket)) {
-			ipsec6stat.in_polvio++;
+		if (ipsec6_in_reject_so(m, last->inp_socket, vnet)) {
+			vnet->ipsec6stat.in_polvio++;
 			goto bad;
 		}
 #endif /* IPSEC */
@@ -383,8 +383,8 @@
 	/*
 	 * Check AH/ESP integrity.
 	 */
-	if (ipsec6_in_reject_so(m, in6p->in6p_socket)) {
-		ipsec6stat.in_polvio++;
+	if (ipsec6_in_reject_so(m, in6p->in6p_socket, vnet)) {
+		vnet->ipsec6stat.in_polvio++;
 		goto bad;
 	}
 #endif /* IPSEC */
diff -urN sys/netipsec/ipsec.c sys.CORE/netipsec/ipsec.c
--- sys/netipsec/ipsec.c	Mon Jun 30 18:38:13 2003
+++ sys.CORE/netipsec/ipsec.c	Wed Jan 31 16:02:43 2007
@@ -53,6 +53,7 @@
 #include <sys/sysctl.h>
 #include <sys/proc.h>
 
+#include <net/vnet.h>
 #include <net/if.h>
 #include <net/route.h>
 
@@ -123,31 +124,31 @@
 SYSCTL_DECL(_net_inet_ipsec);
 
 /* net.inet.ipsec */
-SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEF_POLICY,
+SYSCTL_V_INT(V_NET, _net_inet_ipsec, IPSECCTL_DEF_POLICY,
 	def_policy, CTLFLAG_RW,	&ip4_def_policy.policy,	0, "");
-SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEF_ESP_TRANSLEV, esp_trans_deflev,
+SYSCTL_V_INT(V_NET, _net_inet_ipsec, IPSECCTL_DEF_ESP_TRANSLEV,esp_trans_deflev,
 	CTLFLAG_RW, &ip4_esp_trans_deflev,	0, "");
-SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEF_ESP_NETLEV, esp_net_deflev,
+SYSCTL_V_INT(V_NET, _net_inet_ipsec, IPSECCTL_DEF_ESP_NETLEV, esp_net_deflev,
 	CTLFLAG_RW, &ip4_esp_net_deflev,	0, "");
-SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEF_AH_TRANSLEV, ah_trans_deflev,
+SYSCTL_V_INT(V_NET, _net_inet_ipsec, IPSECCTL_DEF_AH_TRANSLEV, ah_trans_deflev,
 	CTLFLAG_RW, &ip4_ah_trans_deflev,	0, "");
-SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEF_AH_NETLEV, ah_net_deflev,
+SYSCTL_V_INT(V_NET, _net_inet_ipsec, IPSECCTL_DEF_AH_NETLEV, ah_net_deflev,
 	CTLFLAG_RW, &ip4_ah_net_deflev,	0, "");
-SYSCTL_INT(_net_inet_ipsec, IPSECCTL_AH_CLEARTOS,
+SYSCTL_V_INT(V_NET, _net_inet_ipsec, IPSECCTL_AH_CLEARTOS,
 	ah_cleartos, CTLFLAG_RW,	&ah_cleartos,	0, "");
-SYSCTL_INT(_net_inet_ipsec, IPSECCTL_AH_OFFSETMASK,
+SYSCTL_V_INT(V_NET, _net_inet_ipsec, IPSECCTL_AH_OFFSETMASK,
 	ah_offsetmask, CTLFLAG_RW,	&ip4_ah_offsetmask,	0, "");
-SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DFBIT,
+SYSCTL_V_INT(V_NET, _net_inet_ipsec, IPSECCTL_DFBIT,
 	dfbit, CTLFLAG_RW,	&ip4_ipsec_dfbit,	0, "");
-SYSCTL_INT(_net_inet_ipsec, IPSECCTL_ECN,
+SYSCTL_V_INT(V_NET, _net_inet_ipsec, IPSECCTL_ECN,
 	ecn, CTLFLAG_RW,	&ip4_ipsec_ecn,	0, "");
-SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEBUG,
+SYSCTL_V_INT(V_NET, _net_inet_ipsec, IPSECCTL_DEBUG,
 	debug, CTLFLAG_RW,	&ipsec_debug,	0, "");
-SYSCTL_INT(_net_inet_ipsec, IPSECCTL_ESP_RANDPAD,
+SYSCTL_V_INT(V_NET, _net_inet_ipsec, IPSECCTL_ESP_RANDPAD,
 	esp_randpad, CTLFLAG_RW,	&ip4_esp_randpad,	0, "");
-SYSCTL_INT(_net_inet_ipsec, OID_AUTO,
+SYSCTL_V_INT(V_NET, _net_inet_ipsec, OID_AUTO,
 	crypto_support,	CTLFLAG_RW,	&crypto_support,0, "");
-SYSCTL_STRUCT(_net_inet_ipsec, OID_AUTO,
+SYSCTL_V_STRUCT(V_NET, _net_inet_ipsec, OID_AUTO,
 	ipsecstats,	CTLFLAG_RD,	&newipsecstat,	newipsecstat, "");
 
 #ifdef INET6
@@ -165,21 +166,21 @@
 SYSCTL_OID(_net_inet6_ipsec6, IPSECCTL_STATS, stats, CTLFLAG_RD,
 	0,0, compat_ipsecstats_sysctl, "S", "");
 #endif /* COMPAT_KAME */
-SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEF_POLICY,
+SYSCTL_V_INT(V_NET, _net_inet6_ipsec6, IPSECCTL_DEF_POLICY,
 	def_policy, CTLFLAG_RW,	&ip4_def_policy.policy,	0, "");
-SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEF_ESP_TRANSLEV, esp_trans_deflev,
-	CTLFLAG_RW, &ip6_esp_trans_deflev,	0, "");
-SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEF_ESP_NETLEV, esp_net_deflev,
+SYSCTL_V_INT(V_NET, _net_inet6_ipsec6, IPSECCTL_DEF_ESP_TRANSLEV, 
+	esp_trans_deflev, CTLFLAG_RW, &ip6_esp_trans_deflev,	0, "");
+SYSCTL_V_INT(V_NET, _net_inet6_ipsec6, IPSECCTL_DEF_ESP_NETLEV, esp_net_deflev,
 	CTLFLAG_RW, &ip6_esp_net_deflev,	0, "");
-SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEF_AH_TRANSLEV, ah_trans_deflev,
-	CTLFLAG_RW, &ip6_ah_trans_deflev,	0, "");
-SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEF_AH_NETLEV, ah_net_deflev,
+SYSCTL_V_INT(V_NET, _net_inet6_ipsec6, IPSECCTL_DEF_AH_TRANSLEV,
+	ah_trans_deflev, CTLFLAG_RW, &ip6_ah_trans_deflev,	0, "");
+SYSCTL_V_INT(V_NET, _net_inet6_ipsec6, IPSECCTL_DEF_AH_NETLEV, ah_net_deflev,
 	CTLFLAG_RW, &ip6_ah_net_deflev,	0, "");
-SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_ECN,
+SYSCTL_V_INT(V_NET, _net_inet6_ipsec6, IPSECCTL_ECN,
 	ecn, CTLFLAG_RW,	&ip6_ipsec_ecn,	0, "");
-SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEBUG,
+SYSCTL_V_INT(V_NET, _net_inet6_ipsec6, IPSECCTL_DEBUG,
 	debug, CTLFLAG_RW,	&ipsec_debug,	0, "");
-SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_ESP_RANDPAD,
+SYSCTL_V_INT(V_NET, _net_inet6_ipsec6, IPSECCTL_ESP_RANDPAD,
 	esp_randpad, CTLFLAG_RW,	&ip6_esp_randpad,	0, "");
 #endif /* INET6 */
 
diff -urN sys/netipsec/key.c sys.CORE/netipsec/key.c
--- sys/netipsec/key.c	Sat Feb 14 14:23:23 2004
+++ sys.CORE/netipsec/key.c	Wed Jan 31 16:02:43 2007
@@ -54,6 +54,7 @@
 #include <sys/queue.h>
 #include <sys/syslog.h>
 
+#include <net/vnet.h>
 #include <net/if.h>
 #include <net/route.h>
 #include <net/raw_cb.h>
@@ -203,51 +204,51 @@
 SYSCTL_DECL(_net_key);
 #endif
 
-SYSCTL_INT(_net_key, KEYCTL_DEBUG_LEVEL,	debug,	CTLFLAG_RW, \
+SYSCTL_V_INT(V_NET, _net_key, KEYCTL_DEBUG_LEVEL,	debug,	CTLFLAG_RW, \
 	&key_debug_level,	0,	"");
 
 /* max count of trial for the decision of spi value */
-SYSCTL_INT(_net_key, KEYCTL_SPI_TRY,		spi_trycnt,	CTLFLAG_RW, \
+SYSCTL_V_INT(V_NET, _net_key, KEYCTL_SPI_TRY,	spi_trycnt,	CTLFLAG_RW, \
 	&key_spi_trycnt,	0,	"");
 
 /* minimum spi value to allocate automatically. */
-SYSCTL_INT(_net_key, KEYCTL_SPI_MIN_VALUE,	spi_minval,	CTLFLAG_RW, \
+SYSCTL_V_INT(V_NET, _net_key, KEYCTL_SPI_MIN_VALUE, spi_minval, CTLFLAG_RW, \
 	&key_spi_minval,	0,	"");
 
 /* maximun spi value to allocate automatically. */
-SYSCTL_INT(_net_key, KEYCTL_SPI_MAX_VALUE,	spi_maxval,	CTLFLAG_RW, \
+SYSCTL_V_INT(V_NET, _net_key, KEYCTL_SPI_MAX_VALUE, spi_maxval, CTLFLAG_RW, \
 	&key_spi_maxval,	0,	"");
 
 /* interval to initialize randseed */
-SYSCTL_INT(_net_key, KEYCTL_RANDOM_INT,	int_random,	CTLFLAG_RW, \
+SYSCTL_V_INT(V_NET, _net_key, KEYCTL_RANDOM_INT, int_random,	CTLFLAG_RW, \
 	&key_int_random,	0,	"");
 
 /* lifetime for larval SA */
-SYSCTL_INT(_net_key, KEYCTL_LARVAL_LIFETIME,	larval_lifetime, CTLFLAG_RW, \
+SYSCTL_V_INT(V_NET, _net_key, KEYCTL_LARVAL_LIFETIME, larval_lifetime, CTLFLAG_RW, \
 	&key_larval_lifetime,	0,	"");
 
 /* counter for blocking to send SADB_ACQUIRE to IKEd */
-SYSCTL_INT(_net_key, KEYCTL_BLOCKACQ_COUNT,	blockacq_count,	CTLFLAG_RW, \
+SYSCTL_V_INT(V_NET, _net_key, KEYCTL_BLOCKACQ_COUNT,blockacq_count,CTLFLAG_RW, \
 	&key_blockacq_count,	0,	"");
 
 /* lifetime for blocking to send SADB_ACQUIRE to IKEd */
-SYSCTL_INT(_net_key, KEYCTL_BLOCKACQ_LIFETIME,	blockacq_lifetime, CTLFLAG_RW, \
+SYSCTL_V_INT(V_NET, _net_key, KEYCTL_BLOCKACQ_LIFETIME,	blockacq_lifetime, CTLFLAG_RW, \
 	&key_blockacq_lifetime,	0,	"");
 
 /* ESP auth */
-SYSCTL_INT(_net_key, KEYCTL_ESP_AUTH,	esp_auth, CTLFLAG_RW, \
+SYSCTL_V_INT(V_NET, _net_key, KEYCTL_ESP_AUTH, esp_auth, CTLFLAG_RW, \
 	&ipsec_esp_auth,	0,	"");
 
 /* minimum ESP key length */
-SYSCTL_INT(_net_key, KEYCTL_ESP_KEYMIN,	esp_keymin, CTLFLAG_RW, \
+SYSCTL_V_INT(V_NET, _net_key, KEYCTL_ESP_KEYMIN, esp_keymin, CTLFLAG_RW, \
 	&ipsec_esp_keymin,	0,	"");
 
 /* minimum AH key length */
-SYSCTL_INT(_net_key, KEYCTL_AH_KEYMIN,	ah_keymin, CTLFLAG_RW, \
+SYSCTL_V_INT(V_NET, _net_key, KEYCTL_AH_KEYMIN,	ah_keymin, CTLFLAG_RW, \
 	&ipsec_ah_keymin,	0,	"");
 
 /* perfered old SA rather than new SA */
-SYSCTL_INT(_net_key, KEYCTL_PREFERED_OLDSA,	prefered_oldsa, CTLFLAG_RW,\
+SYSCTL_V_INT(V_NET, _net_key, KEYCTL_PREFERED_OLDSA,prefered_oldsa, CTLFLAG_RW,\
 	&key_prefered_oldsa,	0,	"");
 
 #ifndef LIST_FOREACH
@@ -349,12 +350,13 @@
 	int extlen[SADB_EXT_MAX + 1];
 };
 
-static struct secasvar *key_allocsa_policy __P((const struct secasindex *));
+static struct secasvar *key_allocsa_policy __P((const struct secasindex *,
+	struct vnet *));
 static void key_freesp_so __P((struct secpolicy **));
 static struct secasvar *key_do_allocsa_policy __P((struct secashead *, u_int));
 static void key_delsp __P((struct secpolicy *));
-static struct secpolicy *key_getsp __P((struct secpolicyindex *));
-static struct secpolicy *key_getspbyid __P((u_int32_t));
+static struct secpolicy *key_getsp __P((struct secpolicyindex *, struct vnet*));
+static struct secpolicy *key_getspbyid __P((u_int32_t, struct vnet *));
 static u_int32_t key_newreqid __P((void));
 static struct mbuf *key_gather_mbuf __P((struct mbuf *,
 	const struct sadb_msghdr *, int, int, ...));
@@ -523,7 +525,7 @@
  *	others:	found and return the pointer.
  */
 struct secpolicy *
-key_allocsp(struct secpolicyindex *spidx, u_int dir, const char* where, int tag)
+key_allocsp(struct secpolicyindex *spidx, u_int dir, const char* where, int tag, struct vnet *vnet)
 {
 	struct secpolicy *sp;
 	int s;
@@ -541,7 +543,7 @@
 		printf("*** objects\n");
 		kdebug_secpolicyindex(spidx));
 
-	LIST_FOREACH(sp, &sptree[dir], chain) {
+	LIST_FOREACH(sp, &vnet->sptree[dir], chain) {
 		KEYDEBUG(KEYDEBUG_IPSEC_DATA,
 			printf("*** in SPD\n");
 			kdebug_secpolicyindex(&sp->spidx));
@@ -580,7 +582,7 @@
 	     union sockaddr_union *dst,
 	     u_int8_t proto,
 	     u_int dir,
-	     const char* where, int tag)
+	     const char* where, int tag, struct vnet *vnet)
 {
 	struct secpolicy *sp;
 	int s;
@@ -599,7 +601,7 @@
 		printf("spi %u proto %u dir %u\n", spi, proto, dir);
 		kdebug_sockaddr(&dst->sa));
 
-	LIST_FOREACH(sp, &sptree[dir], chain) {
+	LIST_FOREACH(sp, &vnet->sptree[dir], chain) {
 		KEYDEBUG(KEYDEBUG_IPSEC_DATA,
 			printf("*** in SPD\n");
 			kdebug_secpolicyindex(&sp->spidx));
@@ -642,7 +644,7 @@
 	      const struct sockaddr *odst,
 	      const struct sockaddr *isrc,
 	      const struct sockaddr *idst,
-	      const char* where, int tag)
+	      const char* where, int tag, struct vnet *vnet)
 {
 	struct secpolicy *sp;
 	const int dir = IPSEC_DIR_INBOUND;
@@ -661,7 +663,7 @@
 	}
 
 	s = splnet();	/*called from softclock()*/
-	LIST_FOREACH(sp, &sptree[dir], chain) {
+	LIST_FOREACH(sp, &vnet->sptree[dir], chain) {
 		if (sp->state == IPSEC_SPSTATE_DEAD)
 			continue;
 
@@ -817,7 +819,7 @@
 	struct secasvar *sav;
 	u_int stateidx, state;
 
-	LIST_FOREACH(sah, &sahtree, chain) {
+	LIST_FOREACH(sah, &vnet->sahtree, chain) {
 		if (sah->state == SADB_SASTATE_DEAD)
 			continue;
 		if (key_cmpsaidx(&sah->saidx, saidx, CMP_MODE_REQID))
@@ -991,7 +993,7 @@
 	union sockaddr_union *dst,
 	u_int proto,
 	u_int32_t spi,
-	const char* where, int tag)
+	const char* where, int tag, struct vnet *vnet)
 {
 	struct secashead *sah;
 	struct secasvar *sav;
@@ -1010,7 +1012,7 @@
 	 * encrypted so we can't check internal IP header.
 	 */
 	s = splnet();	/*called from softclock()*/
-	LIST_FOREACH(sah, &sahtree, chain) {
+	LIST_FOREACH(sah, &vnet->sahtree, chain) {
 		/* search valid state */
 		for (stateidx = 0;
 		     stateidx < _ARRAYLEN(saorder_state_valid);
@@ -1213,13 +1215,13 @@
  *	others	: found, pointer to a SP.
  */
 static struct secpolicy *
-key_getsp(struct secpolicyindex *spidx)
+key_getsp(struct secpolicyindex *spidx, struct vnet *vnet)
 {
 	struct secpolicy *sp;
 
 	KASSERT(spidx != NULL, ("key_getsp: null spidx"));
 
-	LIST_FOREACH(sp, &sptree[spidx->dir], chain) {
+	LIST_FOREACH(sp, &vnet->sptree[spidx->dir], chain) {
 		if (sp->state == IPSEC_SPSTATE_DEAD)
 			continue;
 		if (key_cmpspidx_exactly(spidx, &sp->spidx)) {
@@ -1237,11 +1239,11 @@
  *	others	: found, pointer to a SP.
  */
 static struct secpolicy *
-key_getspbyid(u_int32_t id)
+key_getspbyid(u_int32_t id, struct vnet *vnet)
 {
 	struct secpolicy *sp;
 
-	LIST_FOREACH(sp, &sptree[IPSEC_DIR_INBOUND], chain) {
+	LIST_FOREACH(sp, &vnet->sptree[IPSEC_DIR_INBOUND], chain) {
 		if (sp->state == IPSEC_SPSTATE_DEAD)
 			continue;
 		if (sp->id == id) {
@@ -1250,7 +1252,7 @@
 		}
 	}
 
-	LIST_FOREACH(sp, &sptree[IPSEC_DIR_OUTBOUND], chain) {
+	LIST_FOREACH(sp, &vnet->sptree[IPSEC_DIR_OUTBOUND], chain) {
 		if (sp->state == IPSEC_SPSTATE_DEAD)
 			continue;
 		if (sp->id == id) {
@@ -7060,37 +7062,59 @@
 }
 
 void
-key_init()
+key_init(vnet)
+	struct vnet *vnet;
 {
 	int i;
 
 	for (i = 0; i < IPSEC_DIR_MAX; i++) {
-		LIST_INIT(&sptree[i]);
+		LIST_INIT(&vnet->sptree[i]);
 	}
 
-	LIST_INIT(&sahtree);
+	LIST_INIT(&vnet->sahtree);
 
 	for (i = 0; i <= SADB_SATYPE_MAX; i++) {
-		LIST_INIT(&regtree[i]);
+		LIST_INIT(&vnet->regtree[i]);
 	}
 
 #ifndef IPSEC_NONBLOCK_ACQUIRE
-	LIST_INIT(&acqtree);
+	LIST_INIT(&vnet->acqtree);
 #endif
-	LIST_INIT(&spacqtree);
+	LIST_INIT(&vnet->spacqtree);
 
 	/* system default */
-	ip4_def_policy.policy = IPSEC_POLICY_NONE;
-	ip4_def_policy.refcnt++;	/*never reclaim this*/
+	vnet->ip4_def_policy.policy = IPSEC_POLICY_NONE;
+	vnet->ip4_def_policy.refcnt++;	/*never reclaim this*/
 
 #ifndef IPSEC_DEBUG2
 	timeout((void *)key_timehandler, (void *)0, hz);
 #endif /*IPSEC_DEBUG2*/
 
 	/* initialize key statistics */
-	keystat.getspi_count = 1;
+	vnet->keystat.getspi_count = 1;
+	
+	/* initialize vars in struct vnet */
+	vnet->acq_seq = 0;
+	vnet->ip4_ah_offsetmask = 0;
+	vnet->ip4_ipsec_dfbit = 0;
+	vnet->ip4_esp_trans_deflev = IPSEC_LEVEL_USE;
+	vnet->ip4_esp_net_deflev = IPSEC_LEVEL_USE;
+	vnet->ip4_ah_trans_deflev = IPSEC_LEVEL_USE;
+	vnet->ip4_ah_net_deflev = IPSEC_LEVEL_USE;
+	vnet->ip4_ipsec_ecn = 0;
+	vnet->ip4_esp_randpad = -1;
+	vnet->crypto_support = 0;
+#ifdef INET6
+	vnet->ip6_esp_trans_deflev = IPSEC_LEVEL_USE;
+	vnet->ip6_esp_net_deflev = IPSEC_LEVEL_USE;
+	vnet->ip6_ah_trans_deflev = IPSEC_LEVEL_USE;
+	vnet->ip6_ah_net_deflev = IPSEC_LEVEL_USE;
+	vnet->ip6_ipsec_ecn = 0;
+	vnet->ip6_esp_randpad = -1;
+#endif
 
-	printf("IPsec: Initialized Security Association Processing.\n");
+	if (vnet == vnet0)
+		printf("IPsec: Initialized Security Association Processing.\n");
 
 	return;
 }
diff -urN sys/netipsec/keysock.c sys.CORE/netipsec/keysock.c
--- sys/netipsec/keysock.c	Thu Jan 23 21:11:36 2003
+++ sys.CORE/netipsec/keysock.c	Wed Jan 31 16:02:43 2007
@@ -592,10 +592,11 @@
 };
 
 static void
-key_init0(void)
+key_init0(vnet)
+	struct vnet *vnet;
 {
-	bzero((caddr_t)&key_cb, sizeof(key_cb));
-	key_init();
+	bzero((caddr_t)&vnet->key_cb, sizeof(key_cb));
+	key_init(vnet);
 }
 
 struct domain keydomain =
diff -urN sys/netkey/key.c sys.CORE/netkey/key.c
--- sys/netkey/key.c	Thu Jan 13 14:47:18 2005
+++ sys.CORE/netkey/key.c	Wed Jan 31 16:02:43 2007
@@ -107,6 +107,8 @@
 #include <sys/random.h>
 
 #include <net/net_osdep.h>
+#include <sys/vimage.h>
+#include <net/vnet.h>
 
 #ifndef satosin
 #define satosin(s) ((struct sockaddr_in *)s)
@@ -126,6 +128,7 @@
  */
 
 u_int32_t key_debug_level = 0;
+#ifdef MOVED_TO_VNET
 static u_int key_spi_trycnt = 1000;
 static u_int32_t key_spi_minval = 0x100;
 static u_int32_t key_spi_maxval = 0x0fffffff;	/* XXX */
@@ -149,6 +152,7 @@
 static LIST_HEAD(_spacqtree, secspacq) spacqtree;	/* SP acquiring list */
 
 struct key_cb key_cb;
+#endif /* MOVED_TO_VNET */
 
 /* search order for SAs */
 static const u_int saorder_state_valid_prefer_old[] = {
@@ -223,32 +227,32 @@
 	&key_debug_level,	0,	"");
 
 /* max count of trial for the decision of spi value */
-SYSCTL_INT(_net_key, KEYCTL_SPI_TRY,		spi_trycnt,	CTLFLAG_RW, \
-	&key_spi_trycnt,	0,	"");
+SYSCTL_V_INT(V_NET, _net_key, KEYCTL_SPI_TRY,		spi_trycnt,	CTLFLAG_RW, \
+	v_key_spi_trycnt,	0,	"");
 
 /* minimum spi value to allocate automatically. */
-SYSCTL_INT(_net_key, KEYCTL_SPI_MIN_VALUE,	spi_minval,	CTLFLAG_RW, \
-	&key_spi_minval,	0,	"");
+SYSCTL_V_INT(V_NET, _net_key, KEYCTL_SPI_MIN_VALUE,	spi_minval,	CTLFLAG_RW, \
+	v_key_spi_minval,	0,	"");
 
 /* maximun spi value to allocate automatically. */
-SYSCTL_INT(_net_key, KEYCTL_SPI_MAX_VALUE,	spi_maxval,	CTLFLAG_RW, \
-	&key_spi_maxval,	0,	"");
+SYSCTL_V_INT(V_NET, _net_key, KEYCTL_SPI_MAX_VALUE,	spi_maxval,	CTLFLAG_RW, \
+	v_key_spi_maxval,	0,	"");
 
 /* interval to initialize randseed */
-SYSCTL_INT(_net_key, KEYCTL_RANDOM_INT,	int_random,	CTLFLAG_RW, \
-	&key_int_random,	0,	"");
+SYSCTL_V_INT(V_NET, _net_key, KEYCTL_RANDOM_INT,	int_random,	CTLFLAG_RW, \
+	v_key_int_random,	0,	"");
 
 /* lifetime for larval SA */
-SYSCTL_INT(_net_key, KEYCTL_LARVAL_LIFETIME,	larval_lifetime, CTLFLAG_RW, \
-	&key_larval_lifetime,	0,	"");
+SYSCTL_V_INT(V_NET, _net_key, KEYCTL_LARVAL_LIFETIME,	larval_lifetime, CTLFLAG_RW, \
+	v_key_larval_lifetime,	0,	"");
 
 /* counter for blocking to send SADB_ACQUIRE to IKEd */
-SYSCTL_INT(_net_key, KEYCTL_BLOCKACQ_COUNT,	blockacq_count,	CTLFLAG_RW, \
-	&key_blockacq_count,	0,	"");
+SYSCTL_V_INT(V_NET, _net_key, KEYCTL_BLOCKACQ_COUNT,	blockacq_count,	CTLFLAG_RW, \
+	v_key_blockacq_count,	0,	"");
 
 /* lifetime for blocking to send SADB_ACQUIRE to IKEd */
-SYSCTL_INT(_net_key, KEYCTL_BLOCKACQ_LIFETIME,	blockacq_lifetime, CTLFLAG_RW, \
-	&key_blockacq_lifetime,	0,	"");
+SYSCTL_V_INT(V_NET, _net_key, KEYCTL_BLOCKACQ_LIFETIME,	blockacq_lifetime, CTLFLAG_RW, \
+	v_key_blockacq_lifetime,	0,	"");
 
 /* ESP auth */
 SYSCTL_INT(_net_key, KEYCTL_ESP_AUTH,	esp_auth, CTLFLAG_RW, \
@@ -263,8 +267,8 @@
 	&ipsec_ah_keymin,	0,	"");
 
 /* perfered old SA rather than new SA */
-SYSCTL_INT(_net_key, KEYCTL_PREFERED_OLDSA,	prefered_oldsa, CTLFLAG_RW,\
-	&key_preferred_oldsa,	0,	"");
+SYSCTL_V_INT(V_NET, _net_key, KEYCTL_PREFERED_OLDSA,	prefered_oldsa, CTLFLAG_RW,\
+	v_key_preferred_oldsa,	0,	"");
 
 #ifndef LIST_FOREACH
 #define LIST_FOREACH(elm, head, field)                                     \
@@ -352,9 +356,11 @@
 } while (0)
 
 /* key statistics */
+#ifdef MOVED_TO_VNET
 struct _keystat {
 	u_long getspi_count; /* the avarage of count to try to get new SPI */
 } keystat;
+#endif
 
 struct sadb_msghdr {
 	struct sadb_msg *msg;
@@ -363,18 +369,20 @@
 	int extlen[SADB_EXT_MAX + 1];
 };
 
-static struct secasvar *key_allocsa_policy __P((struct secasindex *));
+static struct secasvar *key_allocsa_policy __P((struct secasindex *,
+	struct vnet *));
 static void key_freesp_so __P((struct secpolicy **));
-static struct secasvar *key_do_allocsa_policy __P((struct secashead *, u_int));
+static struct secasvar *key_do_allocsa_policy __P((struct secashead *, u_int,
+	struct vnet *));
 static void key_delsp __P((struct secpolicy *));
-static struct secpolicy *key_getsp __P((struct secpolicyindex *));
-static struct secpolicy *key_getspbyid __P((u_int32_t));
+static struct secpolicy *key_getsp __P((struct secpolicyindex *, struct vnet*));
+static struct secpolicy *key_getspbyid __P((u_int32_t, struct vnet*));
 static u_int32_t key_newreqid __P((void));
 static struct mbuf *key_gather_mbuf __P((struct mbuf *,
 	const struct sadb_msghdr *, int, int, ...));
 static int key_spdadd __P((struct socket *, struct mbuf *,
 	const struct sadb_msghdr *));
-static u_int32_t key_getnewspid __P((void));
+static u_int32_t key_getnewspid __P((struct vnet *));
 static int key_spddelete __P((struct socket *, struct mbuf *,
 	const struct sadb_msghdr *));
 static int key_spddelete2 __P((struct socket *, struct mbuf *,
@@ -388,14 +396,15 @@
 static struct mbuf *key_setdumpsp __P((struct secpolicy *,
 	u_int8_t, u_int32_t, u_int32_t));
 static u_int key_getspreqmsglen __P((struct secpolicy *));
-static int key_spdexpire __P((struct secpolicy *));
-static struct secashead *key_newsah __P((struct secasindex *));
+static int key_spdexpire __P((struct secpolicy *, struct vnet *));
+static struct secashead *key_newsah __P((struct secasindex *, struct vnet *));
 static void key_delsah __P((struct secashead *));
 static struct secasvar *key_newsav __P((struct mbuf *,
 	const struct sadb_msghdr *, struct secashead *, int *));
 static void key_delsav __P((struct secasvar *));
-static struct secashead *key_getsah __P((struct secasindex *));
-static struct secasvar *key_checkspidup __P((struct secasindex *, u_int32_t));
+static struct secashead *key_getsah __P((struct secasindex *, struct vnet *));
+static struct secasvar *key_checkspidup __P((struct secasindex *, u_int32_t, 
+	struct vnet *));
 static struct secasvar *key_getsavbyspi __P((struct secashead *, u_int32_t));
 static int key_setsaval __P((struct secasvar *, struct mbuf *,
 	const struct sadb_msghdr *));
@@ -416,7 +425,7 @@
 	u_int32_t));
 static void *key_newbuf __P((const void *, u_int));
 #ifdef INET6
-static int key_ismyaddr6 __P((struct sockaddr_in6 *));
+static int key_ismyaddr6 __P((struct sockaddr_in6 *, struct vnet *));
 #endif
 
 /* flags for key_cmpsaidx() */
@@ -440,7 +449,8 @@
 static int key_getspi __P((struct socket *, struct mbuf *,
 	const struct sadb_msghdr *));
 static u_int32_t key_do_getnewspi __P((struct sadb_spirange *,
-					struct secasindex *));
+					struct secasindex *,
+					struct vnet *));
 static int key_update __P((struct socket *, struct mbuf *,
 	const struct sadb_msghdr *));
 #ifdef IPSEC_DOSEQCHECK
@@ -465,19 +475,20 @@
 static struct mbuf *key_getcomb_ipcomp __P((void));
 static struct mbuf *key_getprop __P((const struct secasindex *));
 
-static int key_acquire __P((struct secasindex *, struct secpolicy *));
+static int key_acquire __P((struct secasindex *, struct secpolicy *,
+	struct vnet *));
 #ifndef IPSEC_NONBLOCK_ACQUIRE
-static struct secacq *key_newacq __P((struct secasindex *));
-static struct secacq *key_getacq __P((struct secasindex *));
-static struct secacq *key_getacqbyseq __P((u_int32_t));
+static struct secacq *key_newacq __P((struct secasindex *, struct vnet *));
+static struct secacq *key_getacq __P((struct secasindex *, struct vnet *));
+static struct secacq *key_getacqbyseq __P((u_int32_t, struct vnet *));
 #endif
 static struct secspacq *key_newspacq __P((struct secpolicyindex *));
-static struct secspacq *key_getspacq __P((struct secpolicyindex *));
+static struct secspacq *key_getspacq __P((struct secpolicyindex *, struct vnet *));
 static int key_acquire2 __P((struct socket *, struct mbuf *,
 	const struct sadb_msghdr *));
 static int key_register __P((struct socket *, struct mbuf *,
 	const struct sadb_msghdr *));
-static int key_expire __P((struct secasvar *));
+static int key_expire __P((struct secasvar *, struct vnet *vnet));
 static int key_flush __P((struct socket *, struct mbuf *,
 	const struct sadb_msghdr *));
 static int key_dump __P((struct socket *, struct mbuf *,
@@ -486,7 +497,7 @@
 	const struct sadb_msghdr *));
 static int key_senderror __P((struct socket *, struct mbuf *, int));
 static int key_validate_ext __P((const struct sadb_ext *, int));
-static int key_align __P((struct mbuf *, struct sadb_msghdr *));
+static int key_align __P((struct mbuf *, struct sadb_msghdr *, struct vnet *));
 #if 0
 static const char *key_getfqdn __P((void));
 static const char *key_getuserfqdn __P((void));
@@ -502,9 +513,10 @@
  *	others:	found and return the pointer.
  */
 struct secpolicy *
-key_allocsp(spidx, dir)
+key_allocsp(spidx, dir, vnet)
 	struct secpolicyindex *spidx;
 	u_int dir;
+	struct vnet *vnet;
 {
 	struct secpolicy *sp;
 	struct timeval tv;
@@ -513,6 +525,8 @@
 	/* sanity check */
 	if (spidx == NULL)
 		panic("key_allocsp: NULL pointer is passed.\n");
+	if (vnet == NULL)
+		panic("key_allocsp: NULL vnet is passed.\n");
 
 	/* check direction */
 	switch (dir) {
@@ -529,7 +543,7 @@
 		printf("*** objects\n");
 		kdebug_secpolicyindex(spidx));
 
-	LIST_FOREACH(sp, &sptree[dir], chain) {
+	LIST_FOREACH(sp, &vnet->sptree[dir], chain) {
 		KEYDEBUG(KEYDEBUG_IPSEC_DATA,
 			printf("*** in SPD\n");
 			kdebug_secpolicyindex(&sp->spidx));
@@ -564,8 +578,9 @@
  * XXX slow
  */
 struct secpolicy *
-key_gettunnel(osrc, odst, isrc, idst)
+key_gettunnel(osrc, odst, isrc, idst, vnet)
 	struct sockaddr *osrc, *odst, *isrc, *idst;
+	struct vnet *vnet;
 {
 	struct secpolicy *sp;
 	const int dir = IPSEC_DIR_INBOUND;
@@ -580,9 +595,11 @@
 			isrc->sa_family, idst->sa_family));
 		return NULL;
 	}
+	if (vnet == NULL)
+		panic("key_gettunnel: NULL vnet is passed.\n");
 
 	s = splnet();	/*called from softclock()*/
-	LIST_FOREACH(sp, &sptree[dir], chain) {
+	LIST_FOREACH(sp, &vnet->sptree[dir], chain) {
 		if (sp->state == IPSEC_SPSTATE_DEAD)
 			continue;
 
@@ -639,9 +656,10 @@
  *	ENOENT: policy may be valid, but SA with REQUIRE is on acquiring.
  */
 int
-key_checkrequest(isr, saidx)
+key_checkrequest(isr, saidx, vnet)
 	struct ipsecrequest *isr;
 	struct secasindex *saidx;
+	struct vnet *vnet;
 {
 	u_int level;
 	int error;
@@ -649,6 +667,8 @@
 	/* sanity check */
 	if (isr == NULL || saidx == NULL)
 		panic("key_checkrequest: NULL pointer is passed.\n");
+	if (vnet == NULL)
+		panic("key_checkrequest: NULL vnet is passed.\n");
 
 	/* check mode */
 	switch (saidx->mode) {
@@ -661,7 +681,7 @@
 	}
 
 	/* get current level */
-	level = ipsec_get_reqlevel(isr);
+	level = ipsec_get_reqlevel(isr, vnet);
 
 #if 0
 	/*
@@ -704,14 +724,14 @@
 	 * See key_do_allocsa_policy(), and draft-jenkins-ipsec-rekeying-03.txt.
 	 */
 	if (isr->sav == NULL)
-		isr->sav = key_allocsa_policy(saidx);
+		isr->sav = key_allocsa_policy(saidx, vnet);
 
 	/* When there is SA. */
 	if (isr->sav != NULL)
 		return 0;
 
 	/* there is no SA */
-	if ((error = key_acquire(saidx, isr->sp)) != 0) {
+	if ((error = key_acquire(saidx, isr->sp, vnet)) != 0) {
 		/* XXX What should I do ? */
 		ipseclog((LOG_DEBUG, "key_checkrequest: error %d returned "
 			"from key_acquire.\n", error));
@@ -728,8 +748,9 @@
  *	others:	found and return the pointer.
  */
 static struct secasvar *
-key_allocsa_policy(saidx)
+key_allocsa_policy(saidx, vnet)
 	struct secasindex *saidx;
+	struct vnet *vnet;
 {
 	struct secashead *sah;
 	struct secasvar *sav;
@@ -737,7 +758,9 @@
 	const u_int *saorder_state_valid;
 	int arraysize;
 
-	LIST_FOREACH(sah, &sahtree, chain) {
+	if (vnet == NULL)
+		panic("key_allocsa_policy: NULL vnet is passed.\n");
+	LIST_FOREACH(sah, &vnet->sahtree, chain) {
 		if (sah->state == SADB_SASTATE_DEAD)
 			continue;
 		if (key_cmpsaidx(&sah->saidx, saidx, CMP_MODE_REQID))
@@ -752,7 +775,7 @@
 	 * search a valid state list for outbound packet.
 	 * This search order is important.
 	 */
-	if (key_preferred_oldsa) {
+	if (vnet->key_preferred_oldsa) {
 		saorder_state_valid = saorder_state_valid_prefer_old;
 		arraysize = _ARRAYLEN(saorder_state_valid_prefer_old);
 	} else {
@@ -764,7 +787,7 @@
 
 		state = saorder_state_valid[stateidx];
 
-		sav = key_do_allocsa_policy(sah, state);
+		sav = key_do_allocsa_policy(sah, state, vnet);
 		if (sav != NULL)
 			return sav;
 	}
@@ -780,12 +803,15 @@
  *	others	: found, pointer to a SA.
  */
 static struct secasvar *
-key_do_allocsa_policy(sah, state)
+key_do_allocsa_policy(sah, state, vnet)
 	struct secashead *sah;
 	u_int state;
+	struct vnet *vnet;
 {
 	struct secasvar *sav, *nextsav, *candidate, *d;
 
+	if (vnet == NULL)
+		panic("key_do_allocsa_policy: NULL vnet is passed.\n");
 	/* initilize */
 	candidate = NULL;
 
@@ -812,7 +838,7 @@
 				"lifetime_current is NULL.\n");
 
 		/* What the best method is to compare ? */
-		if (key_preferred_oldsa) {
+		if (vnet->key_preferred_oldsa) {
 			if (candidate->lft_c->sadb_lifetime_addtime >
 					sav->lft_c->sadb_lifetime_addtime) {
 				candidate = sav;
@@ -883,7 +909,7 @@
 				PFKEY_UNIT64(result->m_pkthdr.len);
 
 			if (key_sendup_mbuf(NULL, result,
-					KEY_SENDUP_REGISTERED))
+					KEY_SENDUP_REGISTERED, vnet))
 				goto msgfail;
 		 msgfail:
 			key_freesav(d);
@@ -916,10 +942,11 @@
  * keep source address in IPsec SA.  We see a tricky situation here.
  */
 struct secasvar *
-key_allocsa(family, src, dst, proto, spi)
+key_allocsa(family, src, dst, proto, spi, vnet)
 	u_int family, proto;
 	caddr_t src, dst;
 	u_int32_t spi;
+	struct vnet *vnet;
 {
 	struct secashead *sah;
 	struct secasvar *sav;
@@ -933,12 +960,14 @@
 	/* sanity check */
 	if (src == NULL || dst == NULL)
 		panic("key_allocsa: NULL pointer is passed.\n");
+	if (vnet == NULL)
+		panic("key_allocsa: NULL vnet is passed.\n");
 
 	/*
 	 * when both systems employ similar strategy to use a SA.
 	 * the search order is important even in the inbound case.
 	 */
-	if (key_preferred_oldsa) {
+	if (vnet->key_preferred_oldsa) {
 		saorder_state_valid = saorder_state_valid_prefer_old;
 		arraysize = _ARRAYLEN(saorder_state_valid_prefer_old);
 	} else {
@@ -953,7 +982,7 @@
 	 * encrypted so we can't check internal IP header.
 	 */
 	s = splnet();	/*called from softclock()*/
-	LIST_FOREACH(sah, &sahtree, chain) {
+	LIST_FOREACH(sah, &vnet->sahtree, chain) {
 		/*
 		 * search a valid state list for inbound packet.
 	 	 * the search order is not important.
@@ -1248,16 +1277,19 @@
  *	others	: found, pointer to a SP.
  */
 static struct secpolicy *
-key_getsp(spidx)
+key_getsp(spidx, vnet)
 	struct secpolicyindex *spidx;
+	struct vnet *vnet;
 {
 	struct secpolicy *sp;
 
 	/* sanity check */
 	if (spidx == NULL)
 		panic("key_getsp: NULL pointer is passed.\n");
+	if (vnet == NULL)
+		panic("key_getsp: NULL vnet is passed.\n");
 
-	LIST_FOREACH(sp, &sptree[spidx->dir], chain) {
+	LIST_FOREACH(sp, &vnet->sptree[spidx->dir], chain) {
 		if (sp->state == IPSEC_SPSTATE_DEAD)
 			continue;
 		if (key_cmpspidx_exactly(spidx, &sp->spidx)) {
@@ -1275,12 +1307,15 @@
  *	others	: found, pointer to a SP.
  */
 static struct secpolicy *
-key_getspbyid(id)
+key_getspbyid(id, vnet)
 	u_int32_t id;
+	struct vnet *vnet;
 {
 	struct secpolicy *sp;
 
-	LIST_FOREACH(sp, &sptree[IPSEC_DIR_INBOUND], chain) {
+	if (vnet == NULL)
+		panic("key_getspbyid: NULL vnet is passed.\n");
+	LIST_FOREACH(sp, &vnet->sptree[IPSEC_DIR_INBOUND], chain) {
 		if (sp->state == IPSEC_SPSTATE_DEAD)
 			continue;
 		if (sp->id == id) {
@@ -1289,7 +1324,7 @@
 		}
 	}
 
-	LIST_FOREACH(sp, &sptree[IPSEC_DIR_OUTBOUND], chain) {
+	LIST_FOREACH(sp, &vnet->sptree[IPSEC_DIR_OUTBOUND], chain) {
 		if (sp->state == IPSEC_SPSTATE_DEAD)
 			continue;
 		if (sp->id == id) {
@@ -1735,10 +1770,14 @@
 	struct secpolicy *newsp;
 	struct timeval tv;
 	int error;
+	struct vnet *vnet;
 
 	/* sanity check */
 	if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL)
 		panic("key_spdadd: NULL pointer is passed.\n");
+	vnet = so->so_vnet;
+	if (vnet == NULL)
+		panic("key_spdadd: NULL vnet pointer.\n");
 
 	if (mhp->ext[SADB_EXT_ADDRESS_SRC] == NULL ||
 	    mhp->ext[SADB_EXT_ADDRESS_DST] == NULL ||
@@ -1808,7 +1847,7 @@
 	 * If the type is either SPDADD or SPDSETIDX AND a SP is found,
 	 * then error.
 	 */
-	newsp = key_getsp(&spidx);
+	newsp = key_getsp(&spidx, vnet);
 	if (mhp->msg->sadb_msg_type == SADB_X_SPDUPDATE) {
 		if (newsp) {
 			newsp->state = IPSEC_SPSTATE_DEAD;
@@ -1827,7 +1866,7 @@
 		return key_senderror(so, m, error);
 	}
 
-	if ((newsp->id = key_getnewspid()) == 0) {
+	if ((newsp->id = key_getnewspid(vnet)) == 0) {
 		keydb_delsecpolicy(newsp);
 		return key_senderror(so, m, ENOBUFS);
 	}
@@ -1879,12 +1918,13 @@
 
 	newsp->refcnt = 1;	/* do not reclaim until I say I do */
 	newsp->state = IPSEC_SPSTATE_ALIVE;
-	LIST_INSERT_TAIL(&sptree[newsp->spidx.dir], newsp, secpolicy, chain);
+	LIST_INSERT_TAIL(&vnet->sptree[newsp->spidx.dir], newsp, 
+			secpolicy, chain);
 
 	/* delete the entry in spacqtree */
 	if (mhp->msg->sadb_msg_type == SADB_X_SPDUPDATE) {
 		struct secspacq *spacq;
-		if ((spacq = key_getspacq(&spidx)) != NULL) {
+		if ((spacq = key_getspacq(&spidx, vnet)) != NULL) {
 			/* reset counter in order to deletion by timehandler. */
 			microtime(&tv);
 			spacq->created = tv.tv_sec;
@@ -1934,7 +1974,7 @@
 	xpl->sadb_x_policy_id = newsp->id;
 
 	m_freem(m);
-	return key_sendup_mbuf(so, n, KEY_SENDUP_ALL);
+	return key_sendup_mbuf(so, n, KEY_SENDUP_ALL, vnet);
     }
 }
 
@@ -1945,17 +1985,22 @@
  *	others: success.
  */
 static u_int32_t
-key_getnewspid()
+key_getnewspid(vnet)
+	struct vnet *vnet;
 {
 	u_int32_t newid = 0;
-	int count = key_spi_trycnt;	/* XXX */
+	int count;
 	struct secpolicy *sp;
 
+	if (vnet == NULL)
+		panic("key_getnewspid: NULL vnet was passed.");
+	count = vnet->key_spi_trycnt;	/* XXX */
 	/* when requesting to allocate spi ranged */
 	while (count--) {
-		newid = (policy_id = (policy_id == ~0 ? 1 : policy_id + 1));
+		newid = (vnet->policy_id = (vnet->policy_id == ~0 ? 
+						1 : vnet->policy_id+1));
 
-		if ((sp = key_getspbyid(newid)) == NULL)
+		if ((sp = key_getspbyid(newid, vnet)) == NULL)
 			break;
 
 		key_freesp(sp);
@@ -1991,10 +2036,14 @@
 	struct sadb_x_policy *xpl0;
 	struct secpolicyindex spidx;
 	struct secpolicy *sp;
+	struct vnet *vnet;
 
 	/* sanity check */
 	if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL)
 		panic("key_spddelete: NULL pointer is passed.\n");
+	vnet = so->so_vnet;
+	if (vnet == NULL)
+		panic("key_spddelete: NULL vnet pointer.\n");
 
 	if (mhp->ext[SADB_EXT_ADDRESS_SRC] == NULL ||
 	    mhp->ext[SADB_EXT_ADDRESS_DST] == NULL ||
@@ -2034,7 +2083,7 @@
 	}
 
 	/* Is there SP in SPD ? */
-	if ((sp = key_getsp(&spidx)) == NULL) {
+	if ((sp = key_getsp(&spidx, vnet)) == NULL) {
 		ipseclog((LOG_DEBUG, "key_spddelete: no SP found.\n"));
 		return key_senderror(so, m, EINVAL);
 	}
@@ -2060,7 +2109,7 @@
 	newmsg->sadb_msg_len = PFKEY_UNIT64(n->m_pkthdr.len);
 
 	m_freem(m);
-	return key_sendup_mbuf(so, n, KEY_SENDUP_ALL);
+	return key_sendup_mbuf(so, n, KEY_SENDUP_ALL, vnet);
     }
 }
 
@@ -2084,10 +2133,14 @@
 {
 	u_int32_t id;
 	struct secpolicy *sp;
+	struct vnet *vnet;
 
 	/* sanity check */
 	if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL)
 		panic("key_spddelete2: NULL pointer is passed.\n");
+	vnet = so->so_vnet;
+	if (vnet == NULL)
+		panic("key_spddelete2: NULL vnet pointer.\n");
 
 	if (mhp->ext[SADB_X_EXT_POLICY] == NULL ||
 	    mhp->extlen[SADB_X_EXT_POLICY] < sizeof(struct sadb_x_policy)) {
@@ -2099,7 +2152,7 @@
 	id = ((struct sadb_x_policy *)mhp->ext[SADB_X_EXT_POLICY])->sadb_x_policy_id;
 
 	/* Is there SP in SPD ? */
-	if ((sp = key_getspbyid(id)) == NULL) {
+	if ((sp = key_getspbyid(id, vnet)) == NULL) {
 		ipseclog((LOG_DEBUG, "key_spddelete2: no SP found id:%u.\n", id));
 		key_senderror(so, m, EINVAL);
 	}
@@ -2156,7 +2209,7 @@
 	newmsg->sadb_msg_len = PFKEY_UNIT64(n->m_pkthdr.len);
 
 	m_freem(m);
-	return key_sendup_mbuf(so, n, KEY_SENDUP_ALL);
+	return key_sendup_mbuf(so, n, KEY_SENDUP_ALL, vnet);
     }
 }
 
@@ -2181,10 +2234,14 @@
 	u_int32_t id;
 	struct secpolicy *sp;
 	struct mbuf *n;
+	struct vnet *vnet;
 
 	/* sanity check */
 	if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL)
 		panic("key_spdget: NULL pointer is passed.\n");
+	vnet = so->so_vnet;
+	if (vnet == NULL)
+		panic("key_spdget: NULL vnet pointer.\n");
 
 	if (mhp->ext[SADB_X_EXT_POLICY] == NULL ||
 	    mhp->extlen[SADB_X_EXT_POLICY] < sizeof(struct sadb_x_policy)) {
@@ -2195,7 +2252,7 @@
 	id = ((struct sadb_x_policy *)mhp->ext[SADB_X_EXT_POLICY])->sadb_x_policy_id;
 
 	/* Is there SP in SPD ? */
-	if ((sp = key_getspbyid(id)) == NULL) {
+	if ((sp = key_getspbyid(id, vnet)) == NULL) {
 		ipseclog((LOG_DEBUG, "key_spdget: no SP found id:%u.\n", id));
 		return key_senderror(so, m, ENOENT);
 	}
@@ -2203,7 +2260,7 @@
 	n = key_setdumpsp(sp, SADB_X_SPDGET, 0, mhp->msg->sadb_msg_pid);
 	if (n != NULL) {
 		m_freem(m);
-		return key_sendup_mbuf(so, n, KEY_SENDUP_ONE);
+		return key_sendup_mbuf(so, n, KEY_SENDUP_ONE, vnet);
 	} else
 		return key_senderror(so, m, ENOBUFS);
 }
@@ -2224,8 +2281,9 @@
  *    others: error number
  */
 int
-key_spdacquire(sp)
+key_spdacquire(sp, vnet)
 	struct secpolicy *sp;
+	struct vnet *vnet;
 {
 	struct mbuf *result = NULL, *m;
 	struct secspacq *newspacq;
@@ -2238,10 +2296,12 @@
 		panic("key_spdacquire: called but there is request.\n");
 	if (sp->policy != IPSEC_POLICY_IPSEC)
 		panic("key_spdacquire: policy mismathed. IPsec is expected.\n");
+	if (vnet == NULL)
+		panic("key_spdacquire: NULL vnet is passed.\n");
 
 	/* get a entry to check whether sent message or not. */
-	if ((newspacq = key_getspacq(&sp->spidx)) != NULL) {
-		if (key_blockacq_count < newspacq->count) {
+	if ((newspacq = key_getspacq(&sp->spidx, vnet)) != NULL) {
+		if (vnet->key_blockacq_count < newspacq->count) {
 			/* reset counter and do send message. */
 			newspacq->count = 0;
 		} else {
@@ -2255,7 +2315,7 @@
 			return ENOBUFS;
 
 		/* add to acqtree */
-		LIST_INSERT_HEAD(&spacqtree, newspacq, chain);
+		LIST_INSERT_HEAD(&vnet->spacqtree, newspacq, chain);
 	}
 
 	/* create new sadb_msg to reply. */
@@ -2273,7 +2333,7 @@
 	mtod(result, struct sadb_msg *)->sadb_msg_len =
 	    PFKEY_UNIT64(result->m_pkthdr.len);
 
-	return key_sendup_mbuf(NULL, m, KEY_SENDUP_REGISTERED);
+	return key_sendup_mbuf(NULL, m, KEY_SENDUP_REGISTERED, vnet);
 
 fail:
 	if (result)
@@ -2302,16 +2362,20 @@
 	struct sadb_msg *newmsg;
 	struct secpolicy *sp;
 	u_int dir;
+	struct vnet *vnet;
 
 	/* sanity check */
 	if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL)
 		panic("key_spdflush: NULL pointer is passed.\n");
+	vnet = so->so_vnet;
+	if (vnet == NULL)
+		panic("key_spdflush: NULL vnet pointer.\n");
 
 	if (m->m_len != PFKEY_ALIGN8(sizeof(struct sadb_msg)))
 		return key_senderror(so, m, EINVAL);
 
 	for (dir = 0; dir < IPSEC_DIR_MAX; dir++) {
-		LIST_FOREACH(sp, &sptree[dir], chain) {
+		LIST_FOREACH(sp, &vnet->sptree[dir], chain) {
 			sp->state = IPSEC_SPSTATE_DEAD;
 		}
 	}
@@ -2329,7 +2393,7 @@
 	newmsg->sadb_msg_errno = 0;
 	newmsg->sadb_msg_len = PFKEY_UNIT64(m->m_pkthdr.len);
 
-	return key_sendup_mbuf(so, m, KEY_SENDUP_ALL);
+	return key_sendup_mbuf(so, m, KEY_SENDUP_ALL, vnet);
 }
 
 /*
@@ -2353,15 +2417,19 @@
 	int cnt;
 	u_int dir;
 	struct mbuf *n;
+	struct vnet *vnet;
 
 	/* sanity check */
 	if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL)
 		panic("key_spddump: NULL pointer is passed.\n");
+	vnet = so->so_vnet;
+	if (vnet == NULL)
+		panic("key_spddump: NULL vnet pointer.\n");
 
 	/* search SPD entry and get buffer size. */
 	cnt = 0;
 	for (dir = 0; dir < IPSEC_DIR_MAX; dir++) {
-		LIST_FOREACH(sp, &sptree[dir], chain) {
+		LIST_FOREACH(sp, &vnet->sptree[dir], chain) {
 			cnt++;
 		}
 	}
@@ -2370,13 +2438,13 @@
 		return key_senderror(so, m, ENOENT);
 
 	for (dir = 0; dir < IPSEC_DIR_MAX; dir++) {
-		LIST_FOREACH(sp, &sptree[dir], chain) {
+		LIST_FOREACH(sp, &vnet->sptree[dir], chain) {
 			--cnt;
 			n = key_setdumpsp(sp, SADB_X_SPDDUMP, cnt,
 			    mhp->msg->sadb_msg_pid);
 
 			if (n)
-				key_sendup_mbuf(so, n, KEY_SENDUP_ONE);
+				key_sendup_mbuf(so, n, KEY_SENDUP_ONE, vnet);
 		}
 	}
 
@@ -2481,8 +2549,9 @@
  *	others	: error number
  */
 static int
-key_spdexpire(sp)
+key_spdexpire(sp, vnet)
 	struct secpolicy *sp;
+	struct vnet *vnet;
 {
 	int s;
 	struct mbuf *result = NULL, *m;
@@ -2496,6 +2565,8 @@
 	/* sanity check */
 	if (sp == NULL)
 		panic("key_spdexpire: NULL pointer is passed.\n");
+	if (vnet == NULL)
+		panic("key_spdexpire: NULL vnet is passed.\n");
 
 	/* set msg header */
 	m = key_setsadbmsg(SADB_X_SPDEXPIRE, 0, 0, 0, 0, 0);
@@ -2580,7 +2651,7 @@
 	    PFKEY_UNIT64(result->m_pkthdr.len);
 
 	splx(s);
-	return key_sendup_mbuf(NULL, result, KEY_SENDUP_REGISTERED);
+	return key_sendup_mbuf(NULL, result, KEY_SENDUP_REGISTERED, vnet);
 
  fail:
 	if (result)
@@ -2596,14 +2667,17 @@
  *	others	: pointer to new SA head.
  */
 static struct secashead *
-key_newsah(saidx)
+key_newsah(saidx, vnet)
 	struct secasindex *saidx;
+	struct vnet *vnet;
 {
 	struct secashead *newsah;
 
 	/* sanity check */
 	if (saidx == NULL)
 		panic("key_newsaidx: NULL pointer is passed.\n");
+	if (vnet == NULL)
+		panic("key_newsaidx: NULL vnet is passed.\n");
 
 	newsah = keydb_newsecashead();
 	if (newsah == NULL)
@@ -2613,7 +2687,7 @@
 
 	/* add to saidxtree */
 	newsah->state = SADB_SASTATE_MATURE;
-	LIST_INSERT_HEAD(&sahtree, newsah, chain);
+	LIST_INSERT_HEAD(&vnet->sahtree, newsah, chain);
 
 	return(newsah);
 }
@@ -2846,12 +2920,15 @@
  *	others	: found, pointer to a SA.
  */
 static struct secashead *
-key_getsah(saidx)
+key_getsah(saidx, vnet)
 	struct secasindex *saidx;
+	struct vnet *vnet;
 {
 	struct secashead *sah;
 
-	LIST_FOREACH(sah, &sahtree, chain) {
+	if (vnet == NULL)
+		panic("key_getsah: NULL vnet was passed.");
+	LIST_FOREACH(sah, &vnet->sahtree, chain) {
 		if (sah->state == SADB_SASTATE_DEAD)
 			continue;
 		if (key_cmpsaidx(&sah->saidx, saidx, CMP_REQID))
@@ -2869,13 +2946,16 @@
  *	others	: found, pointer to a SA.
  */
 static struct secasvar *
-key_checkspidup(saidx, spi)
+key_checkspidup(saidx, spi, vnet)
 	struct secasindex *saidx;
 	u_int32_t spi;
+	struct vnet *vnet;
 {
 	struct secashead *sah;
 	struct secasvar *sav;
 
+	if (vnet == NULL)
+		panic("key_checkspidup: NULL vnet was passed.");
 	/* check address family */
 	if (saidx->src.ss_family != saidx->dst.ss_family) {
 		ipseclog((LOG_DEBUG, "key_checkspidup: address family mismatched.\n"));
@@ -2883,8 +2963,8 @@
 	}
 
 	/* check all SAD */
-	LIST_FOREACH(sah, &sahtree, chain) {
-		if (!key_ismyaddr((struct sockaddr *)&sah->saidx.dst))
+	LIST_FOREACH(sah, &vnet->sahtree, chain) {
+		if (!key_ismyaddr((struct sockaddr *)&sah->saidx.dst, vnet))
 			continue;
 		sav = key_getsavbyspi(sah, spi);
 		if (sav != NULL)
@@ -3794,8 +3874,9 @@
  *	0: false
  */
 int
-key_ismyaddr(sa)
+key_ismyaddr(sa, vnet)
 	struct sockaddr *sa;
+	struct vnet *vnet;
 {
 #ifdef INET
 	struct sockaddr_in *sin;
@@ -3805,12 +3886,14 @@
 	/* sanity check */
 	if (sa == NULL)
 		panic("key_ismyaddr: NULL pointer is passed.\n");
+	if (vnet == NULL)
+		panic("key_ismyaddr: NULL vnet was passed.");
 
 	switch (sa->sa_family) {
 #ifdef INET
 	case AF_INET:
 		sin = (struct sockaddr_in *)sa;
-		for (ia = in_ifaddrhead.tqh_first; ia;
+		for (ia = vnet->in_ifaddrhead.tqh_first; ia;
 		     ia = ia->ia_link.tqe_next)
 		{
 			if (sin->sin_family == ia->ia_addr.sin_family &&
@@ -3824,7 +3907,7 @@
 #endif
 #ifdef INET6
 	case AF_INET6:
-		return key_ismyaddr6((struct sockaddr_in6 *)sa);
+		return key_ismyaddr6((struct sockaddr_in6 *)sa, vnet);
 #endif
 	}
 
@@ -3841,13 +3924,16 @@
 #include <netinet6/in6_var.h>
 
 static int
-key_ismyaddr6(sin6)
+key_ismyaddr6(sin6, vnet)
 	struct sockaddr_in6 *sin6;
+	struct vnet *vnet;
 {
 	struct in6_ifaddr *ia;
 	struct in6_multi *in6m;
 
-	for (ia = in6_ifaddr; ia; ia = ia->ia_next) {
+	if (vnet == NULL)
+		panic("key_ismyaddr6: NULL vnet was passed.");
+	for (ia = vnet->in6_ifaddr; ia; ia = ia->ia_next) {
 		if (key_sockaddrcmp((struct sockaddr *)&sin6,
 		    (struct sockaddr *)&ia->ia_addr, 0) == 0)
 			return 1;
@@ -4178,17 +4264,22 @@
 	u_int dir;
 	int s;
 	struct timeval tv;
+	struct vnet *vnet;
 
 	microtime(&tv);
 
 	s = splnet();	/*called from softclock()*/
 
+    /* This timer function is called once to step through every vnet. */
+    LIST_FOREACH(vnet, &vnet_head, vnet_le) 
+    {
+
 	/* SPD */
     {
 	struct secpolicy *sp, *nextsp;
 
 	for (dir = 0; dir < IPSEC_DIR_MAX; dir++) {
-		for (sp = LIST_FIRST(&sptree[dir]);
+		for (sp = LIST_FIRST(&vnet->sptree[dir]);
 		     sp != NULL;
 		     sp = nextsp) {
 
@@ -4208,7 +4299,7 @@
 			 || (sp->validtime
 			  && tv.tv_sec - sp->lastused > sp->validtime)) {
 				sp->state = IPSEC_SPSTATE_DEAD;
-				key_spdexpire(sp);
+				key_spdexpire(sp, vnet);
 				continue;
 			}
 		}
@@ -4220,7 +4311,7 @@
 	struct secashead *sah, *nextsah;
 	struct secasvar *sav, *nextsav;
 
-	for (sah = LIST_FIRST(&sahtree);
+	for (sah = LIST_FIRST(&vnet->sahtree);
 	     sah != NULL;
 	     sah = nextsah) {
 
@@ -4239,7 +4330,7 @@
 
 			nextsav = LIST_NEXT(sav, chain);
 
-			if (tv.tv_sec - sav->created > key_larval_lifetime) {
+			if (tv.tv_sec - sav->created > vnet->key_larval_lifetime) {
 				key_freesav(sav);
 			}
 		}
@@ -4284,7 +4375,7 @@
 					 * message in the status of
 					 * DYING. Do remove below code.
 					 */
-					key_expire(sav);
+					key_expire(sav, vnet);
 				}
 			}
 
@@ -4303,7 +4394,7 @@
 				 * message in the status of
 				 * DYING. Do remove below code.
 				 */
-				key_expire(sav);
+				key_expire(sav, vnet);
 			}
 		}
 
@@ -4387,13 +4478,13 @@
     {
 	struct secacq *acq, *nextacq;
 
-	for (acq = LIST_FIRST(&acqtree);
+	for (acq = LIST_FIRST(&vnet->acqtree);
 	     acq != NULL;
 	     acq = nextacq) {
 
 		nextacq = LIST_NEXT(acq, chain);
 
-		if (tv.tv_sec - acq->created > key_blockacq_lifetime
+		if (tv.tv_sec - acq->created > vnet->key_blockacq_lifetime
 		 && __LIST_CHAINED(acq)) {
 			LIST_REMOVE(acq, chain);
 			KFREE(acq);
@@ -4406,13 +4497,13 @@
     {
 	struct secspacq *acq, *nextacq;
 
-	for (acq = LIST_FIRST(&spacqtree);
+	for (acq = LIST_FIRST(&vnet->spacqtree);
 	     acq != NULL;
 	     acq = nextacq) {
 
 		nextacq = LIST_NEXT(acq, chain);
 
-		if (tv.tv_sec - acq->created > key_blockacq_lifetime
+		if (tv.tv_sec - acq->created > vnet->key_blockacq_lifetime
 		 && __LIST_CHAINED(acq)) {
 			LIST_REMOVE(acq, chain);
 			KFREE(acq);
@@ -4421,11 +4512,13 @@
     }
 
 	/* initialize random seed */
-	if (key_tick_init_random++ > key_int_random) {
-		key_tick_init_random = 0;
+	if (vnet->key_tick_init_random++ > vnet->key_int_random) {
+		vnet->key_tick_init_random = 0;
 		key_srandom();
 	}
 
+    /* end LIST_FOREACH(vnet, ...)  */
+    }
 #ifndef IPSEC_DEBUG2
 	/* do exchange to tick time !! */
 	(void)timeout((void *)key_timehandler, (void *)0, hz);
@@ -4562,10 +4655,14 @@
 	u_int8_t mode;
 	u_int32_t reqid;
 	int error;
+	struct vnet *vnet;
 
 	/* sanity check */
 	if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL)
 		panic("key_getspi: NULL pointer is passed.\n");
+	vnet = so->so_vnet;	
+	if (vnet == NULL)
+		panic("key_getspi: cannot find vnet.\n");
 
 	if (mhp->ext[SADB_EXT_ADDRESS_SRC] == NULL ||
 	    mhp->ext[SADB_EXT_ADDRESS_DST] == NULL) {
@@ -4633,14 +4730,14 @@
 
 	/* SPI allocation */
 	spi = key_do_getnewspi((struct sadb_spirange *)mhp->ext[SADB_EXT_SPIRANGE],
-	                       &saidx);
+	                       &saidx, vnet);
 	if (spi == 0)
 		return key_senderror(so, m, EINVAL);
 
 	/* get a SA index */
-	if ((newsah = key_getsah(&saidx)) == NULL) {
+	if ((newsah = key_getsah(&saidx, vnet)) == NULL) {
 		/* create a new SA index */
-		if ((newsah = key_newsah(&saidx)) == NULL) {
+		if ((newsah = key_newsah(&saidx, vnet)) == NULL) {
 			ipseclog((LOG_DEBUG, "key_getspi: No more memory.\n"));
 			return key_senderror(so, m, ENOBUFS);
 		}
@@ -4661,7 +4758,7 @@
 	/* delete the entry in acqtree */
 	if (mhp->msg->sadb_msg_seq != 0) {
 		struct secacq *acq;
-		if ((acq = key_getacqbyseq(mhp->msg->sadb_msg_seq)) != NULL) {
+		if ((acq = key_getacqbyseq(mhp->msg->sadb_msg_seq, vnet)) != NULL) {
 			/* reset counter in order to deletion by timehandler. */
 			struct timeval tv;
 			microtime(&tv);
@@ -4722,7 +4819,7 @@
 	if (n->m_len < sizeof(struct sadb_msg)) {
 		n = m_pullup(n, sizeof(struct sadb_msg));
 		if (n == NULL)
-			return key_sendup_mbuf(so, m, KEY_SENDUP_ONE);
+			return key_sendup_mbuf(so, m, KEY_SENDUP_ONE, vnet);
 	}
 
 	n->m_pkthdr.len = 0;
@@ -4735,7 +4832,7 @@
 	newmsg->sadb_msg_len = PFKEY_UNIT64(n->m_pkthdr.len);
 
 	m_freem(m);
-	return key_sendup_mbuf(so, n, KEY_SENDUP_ONE);
+	return key_sendup_mbuf(so, n, KEY_SENDUP_ONE, vnet);
     }
 }
 
@@ -4747,21 +4844,26 @@
  *	others: success.
  */
 static u_int32_t
-key_do_getnewspi(spirange, saidx)
+key_do_getnewspi(spirange, saidx, vnet)
 	struct sadb_spirange *spirange;
 	struct secasindex *saidx;
+	struct vnet *vnet;
 {
 	u_int32_t newspi;
 	u_int32_t min, max;
-	int count = key_spi_trycnt;
+	int count;
+
+	if (vnet == NULL)
+		panic("key_do_getnewspi: NULL vnet was passed.");
+	count = vnet->key_spi_trycnt;
 
 	/* set spi range to allocate */
 	if (spirange != NULL) {
 		min = spirange->sadb_spirange_min;
 		max = spirange->sadb_spirange_max;
 	} else {
-		min = key_spi_minval;
-		max = key_spi_maxval;
+		min = vnet->key_spi_minval;
+		max = vnet->key_spi_maxval;
 	}
 	/* IPCOMP needs 2-byte SPI */
 	if (saidx->proto == IPPROTO_IPCOMP) {
@@ -4776,7 +4878,7 @@
 	}
 
 	if (min == max) {
-		if (key_checkspidup(saidx, min) != NULL) {
+		if (key_checkspidup(saidx, min, vnet) != NULL) {
 			ipseclog((LOG_DEBUG, "key_do_getnewspi: SPI %u exists already.\n", min));
 			return 0;
 		}
@@ -4794,7 +4896,7 @@
 			/* generate pseudo-random SPI value ranged. */
 			newspi = min + (key_random() % (max - min + 1));
 
-			if (key_checkspidup(saidx, newspi) == NULL)
+			if (key_checkspidup(saidx, newspi, vnet) == NULL)
 				break;
 		}
 
@@ -4805,8 +4907,8 @@
 	}
 
 	/* statistics */
-	keystat.getspi_count =
-		(keystat.getspi_count + key_spi_trycnt - count) / 2;
+	vnet->keystat.getspi_count =
+		(vnet->keystat.getspi_count + vnet->key_spi_trycnt - count)/2;
 
 	return newspi;
 }
@@ -4839,10 +4941,14 @@
 	u_int8_t mode;
 	u_int32_t reqid;
 	int error;
+	struct vnet *vnet;
 
 	/* sanity check */
 	if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL)
 		panic("key_update: NULL pointer is passed.\n");
+	vnet = so->so_vnet;
+	if (vnet == NULL)
+		panic("key_update: cannot find vnet.\n");
 
 	/* map satype to proto */
 	if ((proto = key_satype2proto(mhp->msg->sadb_msg_satype)) == 0) {
@@ -4887,7 +4993,7 @@
 	KEY_SETSECASIDX(proto, mode, reqid, src0 + 1, dst0 + 1, &saidx);
 
 	/* get a SA header */
-	if ((sah = key_getsah(&saidx)) == NULL) {
+	if ((sah = key_getsah(&saidx, vnet)) == NULL) {
 		ipseclog((LOG_DEBUG, "key_update: no SA index found.\n"));
 		return key_senderror(so, m, ENOENT);
 	}
@@ -4963,7 +5069,7 @@
 	}
 
 	m_freem(m);
-	return key_sendup_mbuf(so, n, KEY_SENDUP_ALL);
+	return key_sendup_mbuf(so, n, KEY_SENDUP_ALL, vnet);
     }
 }
 
@@ -5034,10 +5140,14 @@
 	u_int8_t mode;
 	u_int32_t reqid;
 	int error;
+	struct vnet *vnet;
 
 	/* sanity check */
 	if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL)
 		panic("key_add: NULL pointer is passed.\n");
+	vnet = so->so_vnet;
+	if (vnet == NULL)
+		panic("key_add: NULL vnet pointer is passed.\n");
 
 	/* map satype to proto */
 	if ((proto = key_satype2proto(mhp->msg->sadb_msg_satype)) == 0) {
@@ -5082,9 +5192,9 @@
 	KEY_SETSECASIDX(proto, mode, reqid, src0 + 1, dst0 + 1, &saidx);
 
 	/* get a SA header */
-	if ((newsah = key_getsah(&saidx)) == NULL) {
+	if ((newsah = key_getsah(&saidx, vnet)) == NULL) {
 		/* create a new SA header */
-		if ((newsah = key_newsah(&saidx)) == NULL) {
+		if ((newsah = key_newsah(&saidx, vnet)) == NULL) {
 			ipseclog((LOG_DEBUG, "key_add: No more memory.\n"));
 			return key_senderror(so, m, ENOBUFS);
 		}
@@ -5130,7 +5240,7 @@
 	}
 
 	m_freem(m);
-	return key_sendup_mbuf(so, n, KEY_SENDUP_ALL);
+	return key_sendup_mbuf(so, n, KEY_SENDUP_ALL, vnet);
     }
 }
 
@@ -5265,10 +5375,14 @@
 	struct secashead *sah;
 	struct secasvar *sav = NULL;
 	u_int16_t proto;
+	struct vnet *vnet;
 
 	/* sanity check */
 	if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL)
 		panic("key_delete: NULL pointer is passed.\n");
+	vnet = so->so_vnet;
+	if (vnet == NULL)
+		panic("key_delete: NULL vnet pointer is passed.\n");
 
 	/* map satype to proto */
 	if ((proto = key_satype2proto(mhp->msg->sadb_msg_satype)) == 0) {
@@ -5309,7 +5423,7 @@
 	KEY_SETSECASIDX(proto, IPSEC_MODE_ANY, 0, src0 + 1, dst0 + 1, &saidx);
 
 	/* get a SA header */
-	LIST_FOREACH(sah, &sahtree, chain) {
+	LIST_FOREACH(sah, &vnet->sahtree, chain) {
 		if (sah->state == SADB_SASTATE_DEAD)
 			continue;
 		if (key_cmpsaidx(&sah->saidx, &saidx, CMP_HEAD) == 0)
@@ -5349,7 +5463,7 @@
 	newmsg->sadb_msg_len = PFKEY_UNIT64(n->m_pkthdr.len);
 
 	m_freem(m);
-	return key_sendup_mbuf(so, n, KEY_SENDUP_ALL);
+	return key_sendup_mbuf(so, n, KEY_SENDUP_ALL, vnet);
     }
 }
 
@@ -5368,6 +5482,11 @@
 	struct secashead *sah;
 	struct secasvar *sav, *nextsav;
 	u_int stateidx, state;
+	struct vnet *vnet;
+	
+	if (so == NULL || so->so_vnet == NULL)
+		panic("key_delete_all: cannot find vnet.\n");
+	vnet = so->so_vnet;
 
 	src0 = (struct sadb_address *)(mhp->ext[SADB_EXT_ADDRESS_SRC]);
 	dst0 = (struct sadb_address *)(mhp->ext[SADB_EXT_ADDRESS_DST]);
@@ -5375,7 +5494,7 @@
 	/* XXX boundary check against sa_len */
 	KEY_SETSECASIDX(proto, IPSEC_MODE_ANY, 0, src0 + 1, dst0 + 1, &saidx);
 
-	LIST_FOREACH(sah, &sahtree, chain) {
+	LIST_FOREACH(sah, &vnet->sahtree, chain) {
 		if (sah->state == SADB_SASTATE_DEAD)
 			continue;
 		if (key_cmpsaidx(&sah->saidx, &saidx, CMP_HEAD) == 0)
@@ -5425,7 +5544,7 @@
 	newmsg->sadb_msg_len = PFKEY_UNIT64(n->m_pkthdr.len);
 
 	m_freem(m);
-	return key_sendup_mbuf(so, n, KEY_SENDUP_ALL);
+	return key_sendup_mbuf(so, n, KEY_SENDUP_ALL, vnet);
     }
 }
 
@@ -5453,10 +5572,14 @@
 	struct secashead *sah;
 	struct secasvar *sav = NULL;
 	u_int16_t proto;
+	struct vnet *vnet;
 
 	/* sanity check */
 	if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL)
 		panic("key_get: NULL pointer is passed.\n");
+	vnet = so->so_vnet;
+	if (vnet == NULL)
+		panic("key_get: NULL vnet pointer is passed.\n");
 
 	/* map satype to proto */
 	if ((proto = key_satype2proto(mhp->msg->sadb_msg_satype)) == 0) {
@@ -5485,7 +5608,7 @@
 	KEY_SETSECASIDX(proto, IPSEC_MODE_ANY, 0, src0 + 1, dst0 + 1, &saidx);
 
 	/* get a SA header */
-	LIST_FOREACH(sah, &sahtree, chain) {
+	LIST_FOREACH(sah, &vnet->sahtree, chain) {
 		if (sah->state == SADB_SASTATE_DEAD)
 			continue;
 		if (key_cmpsaidx(&sah->saidx, &saidx, CMP_HEAD) == 0)
@@ -5518,7 +5641,7 @@
 		return key_senderror(so, m, ENOBUFS);
 
 	m_freem(m);
-	return key_sendup_mbuf(so, n, KEY_SENDUP_ONE);
+	return key_sendup_mbuf(so, n, KEY_SENDUP_ONE, vnet);
     }
 }
 
@@ -5795,9 +5918,10 @@
  *    others: error number
  */
 static int
-key_acquire(saidx, sp)
+key_acquire(saidx, sp, vnet)
 	struct secasindex *saidx;
 	struct secpolicy *sp;
+	struct vnet *vnet;
 {
 	struct mbuf *result = NULL, *m;
 #ifndef IPSEC_NONBLOCK_ACQUIRE
@@ -5812,6 +5936,8 @@
 		panic("key_acquire: NULL pointer is passed.\n");
 	if ((satype = key_proto2satype(saidx->proto)) == 0)
 		panic("key_acquire: invalid proto is passed.\n");
+	if (vnet == NULL)
+		panic("key_acquire: NULL vnet is passed.\n");
 
 #ifndef IPSEC_NONBLOCK_ACQUIRE
 	/*
@@ -5821,8 +5947,8 @@
 	 * managed with ACQUIRING list.
 	 */
 	/* get a entry to check whether sending message or not. */
-	if ((newacq = key_getacq(saidx)) != NULL) {
-		if (key_blockacq_count < newacq->count) {
+	if ((newacq = key_getacq(saidx, vnet)) != NULL) {
+		if (vnet->key_blockacq_count < newacq->count) {
 			/* reset counter and do send message. */
 			newacq->count = 0;
 		} else {
@@ -5832,11 +5958,11 @@
 		}
 	} else {
 		/* make new entry for blocking to send SADB_ACQUIRE. */
-		if ((newacq = key_newacq(saidx)) == NULL)
+		if ((newacq = key_newacq(saidx, vnet)) == NULL)
 			return ENOBUFS;
 
 		/* add to acqtree */
-		LIST_INSERT_HEAD(&acqtree, newacq, chain);
+		LIST_INSERT_HEAD(&vnet->acqtree, newacq, chain);
 	}
 #endif
 
@@ -5966,7 +6092,7 @@
 	mtod(result, struct sadb_msg *)->sadb_msg_len =
 	    PFKEY_UNIT64(result->m_pkthdr.len);
 
-	return key_sendup_mbuf(NULL, result, KEY_SENDUP_REGISTERED);
+	return key_sendup_mbuf(NULL, result, KEY_SENDUP_REGISTERED, vnet);
 
  fail:
 	if (result)
@@ -5976,12 +6102,15 @@
 
 #ifndef IPSEC_NONBLOCK_ACQUIRE
 static struct secacq *
-key_newacq(saidx)
+key_newacq(saidx, vnet)
 	struct secasindex *saidx;
+	struct vnet *vnet;
 {
 	struct secacq *newacq;
 	struct timeval tv;
 
+	if (vnet == NULL)
+		panic("key_newacq: NULL vnet was passed.");
 	/* get new entry */
 	KMALLOC(newacq, struct secacq *, sizeof(struct secacq));
 	if (newacq == NULL) {
@@ -5992,7 +6121,7 @@
 
 	/* copy secindex */
 	bcopy(saidx, &newacq->saidx, sizeof(newacq->saidx));
-	newacq->seq = (acq_seq == ~0 ? 1 : ++acq_seq);
+	newacq->seq = (vnet->acq_seq == ~0 ? 1 : ++vnet->acq_seq);
 	microtime(&tv);
 	newacq->created = tv.tv_sec;
 	newacq->count = 0;
@@ -6001,12 +6130,15 @@
 }
 
 static struct secacq *
-key_getacq(saidx)
+key_getacq(saidx, vnet)
 	struct secasindex *saidx;
+	struct vnet *vnet;
 {
 	struct secacq *acq;
 
-	LIST_FOREACH(acq, &acqtree, chain) {
+	if (vnet == NULL)
+		panic("key_getacq: NULL vnet was passed.");
+	LIST_FOREACH(acq, &vnet->acqtree, chain) {
 		if (key_cmpsaidx(saidx, &acq->saidx, CMP_EXACTLY))
 			return acq;
 	}
@@ -6015,12 +6147,15 @@
 }
 
 static struct secacq *
-key_getacqbyseq(seq)
+key_getacqbyseq(seq, vnet)
 	u_int32_t seq;
+	struct vnet *vnet;
 {
 	struct secacq *acq;
 
-	LIST_FOREACH(acq, &acqtree, chain) {
+	if (vnet == NULL)
+		panic("key_getacqbyseq: NULL vnet was passed.");
+	LIST_FOREACH(acq, &vnet->acqtree, chain) {
 		if (acq->seq == seq)
 			return acq;
 	}
@@ -6054,12 +6189,15 @@
 }
 
 static struct secspacq *
-key_getspacq(spidx)
+key_getspacq(spidx, vnet)
 	struct secpolicyindex *spidx;
+	struct vnet *vnet;
 {
 	struct secspacq *acq;
 
-	LIST_FOREACH(acq, &spacqtree, chain) {
+	if (vnet == NULL)
+		panic("key_getspacq: NULL vnet was passed.");
+	LIST_FOREACH(acq, &vnet->spacqtree, chain) {
 		if (key_cmpspidx_exactly(spidx, &acq->spidx))
 			return acq;
 	}
@@ -6092,10 +6230,14 @@
 	struct secashead *sah;
 	u_int16_t proto;
 	int error;
+	struct vnet *vnet;
 
 	/* sanity check */
 	if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL)
 		panic("key_acquire2: NULL pointer is passed.\n");
+	vnet = so->so_vnet;
+	if (vnet == NULL)
+		panic("key_acquire2: NULL vnet pointer is passed.\n");
 
 	/*
 	 * Error message from KMd.
@@ -6115,7 +6257,7 @@
 			return 0;
 		}
 
-		if ((acq = key_getacqbyseq(mhp->msg->sadb_msg_seq)) == NULL) {
+		if ((acq = key_getacqbyseq(mhp->msg->sadb_msg_seq, vnet)) == NULL) {
 			/*
 			 * the specified larval SA is already gone, or we got
 			 * a bogus sequence number.  we can silently ignore it.
@@ -6165,7 +6307,7 @@
 	KEY_SETSECASIDX(proto, IPSEC_MODE_ANY, 0, src0 + 1, dst0 + 1, &saidx);
 
 	/* get a SA index */
-	LIST_FOREACH(sah, &sahtree, chain) {
+	LIST_FOREACH(sah, &vnet->sahtree, chain) {
 		if (sah->state == SADB_SASTATE_DEAD)
 			continue;
 		if (key_cmpsaidx(&sah->saidx, &saidx, CMP_MODE_REQID))
@@ -6176,14 +6318,14 @@
 		return key_senderror(so, m, EEXIST);
 	}
 
-	error = key_acquire(&saidx, NULL);
+	error = key_acquire(&saidx, NULL, vnet);
 	if (error != 0) {
 		ipseclog((LOG_DEBUG, "key_acquire2: error %d returned "
 			"from key_acquire.\n", mhp->msg->sadb_msg_errno));
 		return key_senderror(so, m, error);
 	}
 
-	return key_sendup_mbuf(so, m, KEY_SENDUP_REGISTERED);
+	return key_sendup_mbuf(so, m, KEY_SENDUP_REGISTERED, vnet);
 }
 
 /*
@@ -6206,13 +6348,17 @@
 	const struct sadb_msghdr *mhp;
 {
 	struct secreg *reg, *newreg = 0;
+	struct vnet *vnet;
 
 	/* sanity check */
 	if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL)
 		panic("key_register: NULL pointer is passed.\n");
+	vnet = so->so_vnet;
+	if (vnet == NULL)
+		panic("key_register: NULL vnet is passed.\n");
 
 	/* check for invalid register message */
-	if (mhp->msg->sadb_msg_satype >= sizeof(regtree)/sizeof(regtree[0]))
+	if (mhp->msg->sadb_msg_satype >= sizeof(vnet->regtree)/sizeof(vnet->regtree[0]))
 		return key_senderror(so, m, EINVAL);
 
 	/* When SATYPE_UNSPEC is specified, only return sabd_supported. */
@@ -6220,7 +6366,7 @@
 		goto setmsg;
 
 	/* check whether existing or not */
-	LIST_FOREACH(reg, &regtree[mhp->msg->sadb_msg_satype], chain) {
+	LIST_FOREACH(reg, &vnet->regtree[mhp->msg->sadb_msg_satype], chain) {
 		if (reg->so == so) {
 			ipseclog((LOG_DEBUG, "key_register: socket exists already.\n"));
 			return key_senderror(so, m, EEXIST);
@@ -6239,7 +6385,8 @@
 	((struct keycb *)sotorawcb(so))->kp_registered++;
 
 	/* add regnode to regtree. */
-	LIST_INSERT_HEAD(&regtree[mhp->msg->sadb_msg_satype], newreg, chain);
+	LIST_INSERT_HEAD(&vnet->regtree[mhp->msg->sadb_msg_satype], 
+			newreg, chain);
 
   setmsg:
     {
@@ -6355,7 +6502,7 @@
 #endif
 
 	m_freem(m);
-	return key_sendup_mbuf(so, n, KEY_SENDUP_REGISTERED);
+	return key_sendup_mbuf(so, n, KEY_SENDUP_REGISTERED, vnet);
     }
 }
 
@@ -6369,10 +6516,14 @@
 {
 	struct secreg *reg;
 	int i;
+	struct vnet *vnet;
 
 	/* sanity check */
 	if (so == NULL)
 		panic("key_freereg: NULL pointer is passed.\n");
+	vnet = so->so_vnet;
+	if (vnet == NULL)
+		panic("key_freereg: NULL vnet pointer is passed.\n");
 
 	/*
 	 * check whether existing or not.
@@ -6380,7 +6531,7 @@
 	 * one socket is registered to multiple type of SA.
 	 */
 	for (i = 0; i <= SADB_SATYPE_MAX; i++) {
-		LIST_FOREACH(reg, &regtree[i], chain) {
+		LIST_FOREACH(reg, &vnet->regtree[i], chain) {
 			if (reg->so == so
 			 && __LIST_CHAINED(reg)) {
 				LIST_REMOVE(reg, chain);
@@ -6404,8 +6555,9 @@
  *	others	: error number
  */
 static int
-key_expire(sav)
+key_expire(sav, vnet)
 	struct secasvar *sav;
+	struct vnet *vnet;
 {
 	int s;
 	int satype;
@@ -6414,6 +6566,8 @@
 	int error = -1;
 	struct sadb_lifetime *lt;
 
+	if (vnet == NULL)
+		panic("key_expire: NULL vnet was passed.");
 	/* XXX: Why do we lock ? */
 	s = splnet();	/*called from softclock()*/
 
@@ -6513,7 +6667,7 @@
 	    PFKEY_UNIT64(result->m_pkthdr.len);
 
 	splx(s);
-	return key_sendup_mbuf(NULL, result, KEY_SENDUP_REGISTERED);
+	return key_sendup_mbuf(NULL, result, KEY_SENDUP_REGISTERED, vnet);
 
  fail:
 	if (result)
@@ -6546,10 +6700,14 @@
 	u_int16_t proto;
 	u_int8_t state;
 	u_int stateidx;
+	struct vnet *vnet;
 
 	/* sanity check */
 	if (so == NULL || mhp == NULL || mhp->msg == NULL)
 		panic("key_flush: NULL pointer is passed.\n");
+	vnet = so->so_vnet;
+	if (vnet == NULL)
+		panic("key_flush: NULL vnet pointer is passed.\n");
 
 	/* map satype to proto */
 	if ((proto = key_satype2proto(mhp->msg->sadb_msg_satype)) == 0) {
@@ -6558,7 +6716,7 @@
 	}
 
 	/* no SATYPE specified, i.e. flushing all SA. */
-	for (sah = LIST_FIRST(&sahtree);
+	for (sah = LIST_FIRST(&vnet->sahtree);
 	     sah != NULL;
 	     sah = nextsah) {
 		nextsah = LIST_NEXT(sah, chain);
@@ -6599,7 +6757,7 @@
 	newmsg->sadb_msg_errno = 0;
 	newmsg->sadb_msg_len = PFKEY_UNIT64(m->m_pkthdr.len);
 
-	return key_sendup_mbuf(so, m, KEY_SENDUP_ALL);
+	return key_sendup_mbuf(so, m, KEY_SENDUP_ALL, vnet);
 }
 
 /*
@@ -6629,10 +6787,12 @@
 	int cnt;
 	struct sadb_msg *newmsg;
 	struct mbuf *n;
+	struct vnet *vnet;
 
 	/* sanity check */
 	if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL)
 		panic("key_dump: NULL pointer is passed.\n");
+	vnet = so->so_vnet;
 
 	/* map satype to proto */
 	if ((proto = key_satype2proto(mhp->msg->sadb_msg_satype)) == 0) {
@@ -6642,7 +6802,7 @@
 
 	/* count sav entries to be sent to the userland. */
 	cnt = 0;
-	LIST_FOREACH(sah, &sahtree, chain) {
+	LIST_FOREACH(sah, &vnet->sahtree, chain) {
 		if (mhp->msg->sadb_msg_satype != SADB_SATYPE_UNSPEC
 		 && proto != sah->saidx.proto)
 			continue;
@@ -6662,7 +6822,7 @@
 
 	/* send this to the userland, one at a time. */
 	newmsg = NULL;
-	LIST_FOREACH(sah, &sahtree, chain) {
+	LIST_FOREACH(sah, &vnet->sahtree, chain) {
 		if (mhp->msg->sadb_msg_satype != SADB_SATYPE_UNSPEC
 		 && proto != sah->saidx.proto)
 			continue;
@@ -6683,7 +6843,7 @@
 				if (!n)
 					return key_senderror(so, m, ENOBUFS);
 
-				key_sendup_mbuf(so, n, KEY_SENDUP_ONE);
+				key_sendup_mbuf(so, n, KEY_SENDUP_ONE, vnet);
 			}
 		}
 	}
@@ -6704,10 +6864,14 @@
 	const struct sadb_msghdr *mhp;
 {
 	int olen;
+	struct vnet *vnet;
 
 	/* sanity check */
 	if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL)
 		panic("key_promisc: NULL pointer is passed.\n");
+	vnet = so->so_vnet;
+	if (vnet == NULL);
+		panic("key_promisc: NULL vnet pointer is passed.\n");
 
 	olen = PFKEY_UNUNIT64(mhp->msg->sadb_msg_len);
 
@@ -6736,14 +6900,14 @@
 
 		/* send the original message back to everyone */
 		mhp->msg->sadb_msg_errno = 0;
-		return key_sendup_mbuf(so, m, KEY_SENDUP_ALL);
+		return key_sendup_mbuf(so, m, KEY_SENDUP_ALL, vnet);
 	} else {
 		/* send packet as is */
 
 		m_adj(m, PFKEY_ALIGN8(sizeof(struct sadb_msg)));
 
 		/* TODO: if sadb_msg_seq is specified, send to specific pid */
-		return key_sendup_mbuf(so, m, KEY_SENDUP_ALL);
+		return key_sendup_mbuf(so, m, KEY_SENDUP_ALL, vnet);
 	}
 }
 
@@ -6790,6 +6954,7 @@
 	struct mbuf *m;
 	struct socket *so;
 {
+	struct vnet *vnet;
 	struct sadb_msg *msg;
 	struct sadb_msghdr mh;
 	u_int orglen;
@@ -6799,6 +6964,9 @@
 	/* sanity check */
 	if (m == NULL || so == NULL)
 		panic("key_parse: NULL pointer is passed.\n");
+	vnet = so->so_vnet;	
+	if (vnet == NULL)
+		panic("key_parse: NULL vnet is passed.\n");
 
 #if 0	/*kdebug_sadb assumes msg in linear buffer*/
 	KEYDEBUG(KEYDEBUG_KEY_DUMP,
@@ -6818,7 +6986,7 @@
 	if ((m->m_flags & M_PKTHDR) == 0 ||
 	    m->m_pkthdr.len != m->m_pkthdr.len) {
 		ipseclog((LOG_DEBUG, "key_parse: invalid message length.\n"));
-		pfkeystat.out_invlen++;
+		vnet->pfkeystat.out_invlen++;
 		error = EINVAL;
 		goto senderror;
 	}
@@ -6827,7 +6995,7 @@
 		ipseclog((LOG_DEBUG,
 		    "key_parse: PF_KEY version %u is mismatched.\n",
 		    msg->sadb_msg_version));
-		pfkeystat.out_invver++;
+		vnet->pfkeystat.out_invver++;
 		error = EINVAL;
 		goto senderror;
 	}
@@ -6835,7 +7003,7 @@
 	if (msg->sadb_msg_type > SADB_MAX) {
 		ipseclog((LOG_DEBUG, "key_parse: invalid type %u is passed.\n",
 		    msg->sadb_msg_type));
-		pfkeystat.out_invmsgtype++;
+		vnet->pfkeystat.out_invmsgtype++;
 		error = EINVAL;
 		goto senderror;
 	}
@@ -6868,7 +7036,7 @@
 	}
 
 	/* align the mbuf chain so that extensions are in contiguous region. */
-	error = key_align(m, &mh);
+	error = key_align(m, &mh, vnet);
 	if (error)
 		return error;
 
@@ -6892,7 +7060,7 @@
 		case SADB_EXPIRE:
 			ipseclog((LOG_DEBUG, "key_parse: must specify satype "
 			    "when msg type=%u.\n", msg->sadb_msg_type));
-			pfkeystat.out_invsatype++;
+			vnet->pfkeystat.out_invsatype++;
 			error = EINVAL;
 			goto senderror;
 		}
@@ -6911,7 +7079,7 @@
 		case SADB_X_SPDDELETE2:
 			ipseclog((LOG_DEBUG, "key_parse: illegal satype=%u\n",
 			    msg->sadb_msg_type));
-			pfkeystat.out_invsatype++;
+			vnet->pfkeystat.out_invsatype++;
 			error = EINVAL;
 			goto senderror;
 		}
@@ -6922,7 +7090,7 @@
 	case SADB_SATYPE_MIP:
 		ipseclog((LOG_DEBUG, "key_parse: type %u isn't supported.\n",
 		    msg->sadb_msg_satype));
-		pfkeystat.out_invsatype++;
+		vnet->pfkeystat.out_invsatype++;
 		error = EOPNOTSUPP;
 		goto senderror;
 	case 1:	/* XXX: What does it do? */
@@ -6932,7 +7100,7 @@
 	default:
 		ipseclog((LOG_DEBUG, "key_parse: invalid type %u is passed.\n",
 		    msg->sadb_msg_satype));
-		pfkeystat.out_invsatype++;
+		vnet->pfkeystat.out_invsatype++;
 		error = EINVAL;
 		goto senderror;
 	}
@@ -6949,7 +7117,7 @@
 		/* check upper layer protocol */
 		if (src0->sadb_address_proto != dst0->sadb_address_proto) {
 			ipseclog((LOG_DEBUG, "key_parse: upper layer protocol mismatched.\n"));
-			pfkeystat.out_invaddr++;
+			vnet->pfkeystat.out_invaddr++;
 			error = EINVAL;
 			goto senderror;
 		}
@@ -6958,7 +7126,7 @@
 		if (PFKEY_ADDR_SADDR(src0)->sa_family !=
 		    PFKEY_ADDR_SADDR(dst0)->sa_family) {
 			ipseclog((LOG_DEBUG, "key_parse: address family mismatched.\n"));
-			pfkeystat.out_invaddr++;
+			vnet->pfkeystat.out_invaddr++;
 			error = EINVAL;
 			goto senderror;
 		}
@@ -6966,7 +7134,7 @@
 		    PFKEY_ADDR_SADDR(dst0)->sa_len) {
 			ipseclog((LOG_DEBUG,
 			    "key_parse: address struct size mismatched.\n"));
-			pfkeystat.out_invaddr++;
+			vnet->pfkeystat.out_invaddr++;
 			error = EINVAL;
 			goto senderror;
 		}
@@ -6975,7 +7143,7 @@
 		case AF_INET:
 			if (PFKEY_ADDR_SADDR(src0)->sa_len !=
 			    sizeof(struct sockaddr_in)) {
-				pfkeystat.out_invaddr++;
+				vnet->pfkeystat.out_invaddr++;
 				error = EINVAL;
 				goto senderror;
 			}
@@ -6983,7 +7151,7 @@
 		case AF_INET6:
 			if (PFKEY_ADDR_SADDR(src0)->sa_len !=
 			    sizeof(struct sockaddr_in6)) {
-				pfkeystat.out_invaddr++;
+				vnet->pfkeystat.out_invaddr++;
 				error = EINVAL;
 				goto senderror;
 			}
@@ -6991,7 +7159,7 @@
 		default:
 			ipseclog((LOG_DEBUG,
 			    "key_parse: unsupported address family.\n"));
-			pfkeystat.out_invaddr++;
+			vnet->pfkeystat.out_invaddr++;
 			error = EAFNOSUPPORT;
 			goto senderror;
 		}
@@ -7013,7 +7181,7 @@
 		    dst0->sadb_address_prefixlen > plen) {
 			ipseclog((LOG_DEBUG,
 			    "key_parse: illegal prefixlen.\n"));
-			pfkeystat.out_invaddr++;
+			vnet->pfkeystat.out_invaddr++;
 			error = EINVAL;
 			goto senderror;
 		}
@@ -7026,7 +7194,7 @@
 
 	if (msg->sadb_msg_type >= sizeof(key_typesw)/sizeof(key_typesw[0]) ||
 	    key_typesw[msg->sadb_msg_type] == NULL) {
-		pfkeystat.out_invmsgtype++;
+		vnet->pfkeystat.out_invmsgtype++;
 		error = EINVAL;
 		goto senderror;
 	}
@@ -7035,7 +7203,7 @@
 
 senderror:
 	msg->sadb_msg_errno = error;
-	return key_sendup_mbuf(so, m, target);
+	return key_sendup_mbuf(so, m, target, vnet);
 }
 
 static int
@@ -7044,14 +7212,18 @@
 	struct mbuf *m;
 	int code;
 {
+	struct vnet *vnet;
 	struct sadb_msg *msg;
 
+	if (so == NULL || so->so_vnet == NULL)
+		panic("key_senderror: cannot find vnet");
+	vnet = so->so_vnet;
 	if (m->m_len < sizeof(struct sadb_msg))
 		panic("invalid mbuf passed to key_senderror");
 
 	msg = mtod(m, struct sadb_msg *);
 	msg->sadb_msg_errno = code;
-	return key_sendup_mbuf(so, m, KEY_SENDUP_ONE);
+	return key_sendup_mbuf(so, m, KEY_SENDUP_ONE, vnet);
 }
 
 /*
@@ -7060,9 +7232,10 @@
  * XXX larger-than-MCLBYTES extension?
  */
 static int
-key_align(m, mhp)
+key_align(m, mhp, vnet)
 	struct mbuf *m;
 	struct sadb_msghdr *mhp;
+	struct vnet *vnet;
 {
 	struct mbuf *n;
 	struct sadb_ext *ext;
@@ -7075,6 +7248,8 @@
 		panic("key_align: NULL pointer is passed.\n");
 	if (m->m_len < sizeof(struct sadb_msg))
 		panic("invalid mbuf passed to key_align");
+	if (vnet == NULL)
+		panic("key_align: NULL vnet is passed.\n");
 
 	/* initialize */
 	bzero(mhp, sizeof(*mhp));
@@ -7122,7 +7297,7 @@
 				    "key_align: duplicate ext_type %u "
 				    "is passed.\n", ext->sadb_ext_type));
 				m_freem(m);
-				pfkeystat.out_dupext++;
+				vnet->pfkeystat.out_dupext++;
 				return EINVAL;
 			}
 			break;
@@ -7131,7 +7306,7 @@
 			    "key_align: invalid ext_type %u is passed.\n",
 			    ext->sadb_ext_type));
 			m_freem(m);
-			pfkeystat.out_invexttype++;
+			vnet->pfkeystat.out_invexttype++;
 			return EINVAL;
 		}
 
@@ -7139,7 +7314,7 @@
 
 		if (key_validate_ext(ext, extlen)) {
 			m_freem(m);
-			pfkeystat.out_invlen++;
+			vnet->pfkeystat.out_invlen++;
 			return EINVAL;
 		}
 
@@ -7157,7 +7332,7 @@
 
 	if (off != end) {
 		m_freem(m);
-		pfkeystat.out_invlen++;
+		vnet->pfkeystat.out_invlen++;
 		return EINVAL;
 	}
 
@@ -7224,49 +7399,97 @@
 }
 
 void
-key_init()
+key_init(vnet)
+	struct vnet *vnet;
 {
 	int i;
 
-	bzero((caddr_t)&key_cb, sizeof(key_cb));
+	if (vnet == NULL)
+		panic("key_init: NULL vnet was passed.");
+	bzero((caddr_t)&vnet->key_cb, sizeof(vnet->key_cb));
 
 	for (i = 0; i < IPSEC_DIR_MAX; i++) {
-		LIST_INIT(&sptree[i]);
+		LIST_INIT(&vnet->sptree[i]);
 	}
 
-	LIST_INIT(&sahtree);
+	LIST_INIT(&vnet->sahtree);
 
 	for (i = 0; i <= SADB_SATYPE_MAX; i++) {
-		LIST_INIT(&regtree[i]);
+		LIST_INIT(&vnet->regtree[i]);
 	}
 
 #ifndef IPSEC_NONBLOCK_ACQUIRE
-	LIST_INIT(&acqtree);
+	LIST_INIT(&vnet->acqtree);
 #endif
-	LIST_INIT(&spacqtree);
+	LIST_INIT(&vnet->spacqtree);
 
 	/* system default */
 #ifdef INET
-	ip4_def_policy.policy = IPSEC_POLICY_NONE;
-	ip4_def_policy.refcnt++;	/*never reclaim this*/
+	vnet->ip4_def_policy.policy = IPSEC_POLICY_NONE;
+	vnet->ip4_def_policy.refcnt++;	/*never reclaim this*/
 #endif
 #ifdef INET6
-	ip6_def_policy.policy = IPSEC_POLICY_NONE;
-	ip6_def_policy.refcnt++;	/*never reclaim this*/
+	vnet->ip6_def_policy.policy = IPSEC_POLICY_NONE;
+	vnet->ip6_def_policy.refcnt++;	/*never reclaim this*/
 #endif
 
-#ifndef IPSEC_DEBUG2
-	timeout((void *)key_timehandler, (void *)0, hz);
-#endif /*IPSEC_DEBUG2*/
-
 	/* initialize key statistics */
-	keystat.getspi_count = 1;
+	vnet->keystat.getspi_count = 1;
 
-	printf("IPsec: Initialized Security Association Processing.\n");
+	/* initalize vnet variables (normally static) */
+	/* from netkey/key.c */
+	vnet->key_spi_trycnt = 1000;
+	vnet->key_spi_minval = 0x100;
+	vnet->key_spi_maxval = 0x0fffffff;	/* XXX */
+	vnet->policy_id = 0;
+	vnet->key_int_random = 60;	/*interval to initialize randseed,1(m)*/
+	vnet->key_larval_lifetime = 30;	/* interval to expire acquiring, 30(s)*/
+	vnet->key_blockacq_count = 10;	/* counter for blocking SADB_ACQUIRE.*/
+	vnet->key_blockacq_lifetime = 20;/* lifetime f/ blocking SADB_ACQUIRE.*/
+	vnet->key_preferred_oldsa = 1; /* preferred old sa rather than new sa.*/
+	vnet->acq_seq = 0;
+	vnet->key_tick_init_random = 0;
+
+	/* from netinet6/ipsec.c */
+	vnet->ip4_ah_cleartos = 1;
+	vnet->ip4_ah_offsetmask = 0; /* maybe IP_DF? */
+	vnet->ip4_ipsec_dfbit = 0;/* DF bit on encap. 0: clear 1: set 2: copy */
+	vnet->ip4_esp_trans_deflev = IPSEC_LEVEL_USE;
+	vnet->ip4_esp_net_deflev = IPSEC_LEVEL_USE;
+	vnet->ip4_ah_trans_deflev = IPSEC_LEVEL_USE;
+	vnet->ip4_ah_net_deflev = IPSEC_LEVEL_USE;
+	vnet->ip4_ipsec_ecn = 0; /* ECN ignore(-1)/forbidden(0)/allowed(1) */
+	vnet->ip4_esp_randpad = -1;
+#ifdef INET6
+	/* what about ipsec6stat? */
+	vnet->ip6_esp_trans_deflev = IPSEC_LEVEL_USE;
+	vnet->ip6_esp_net_deflev = IPSEC_LEVEL_USE;
+	vnet->ip6_ah_trans_deflev = IPSEC_LEVEL_USE;
+	vnet->ip6_ah_net_deflev = IPSEC_LEVEL_USE;
+	vnet->ip6_ipsec_ecn = 0; /* ECN ignore(-1)/forbidden(0)/allowed(1) */
+	vnet->ip6_esp_randpad = -1;
+#endif
+
+/* net.inet6.ipsec6 */
+
+#ifndef IPSEC_DEBUG2
+	if (vnet == vnet0) /* one timehandler iterates for all vnets */
+		timeout((void *)key_timehandler, (void *)0, hz);
+#endif /*IPSEC_DEBUG2*/
+	
+	if (vnet == vnet0)
+		printf("IPsec: Initialized Security Association Processing.\n");
 
 	return;
 }
 
+void
+key_destroy(vnet)
+struct vnet *vnet;
+{
+	/* XXX do nothing */
+}
+
 /*
  * XXX: maybe This function is called after INBOUND IPsec processing.
  *
@@ -7406,13 +7629,16 @@
 
 /* dumb version */
 void
-key_sa_routechange(dst)
+key_sa_routechange(dst, vnet)
 	struct sockaddr *dst;
+	struct vnet *vnet;
 {
 	struct secashead *sah;
 	struct route *ro;
 
-	LIST_FOREACH(sah, &sahtree, chain) {
+	if (vnet == NULL)
+		panic("key_sa_routechange: NULL vnet was passed.");
+	LIST_FOREACH(sah, &vnet->sahtree, chain) {
 		ro = &sah->sa_route;
 		if (ro->ro_rt && dst->sa_len == ro->ro_dst.sa_len
 		 && bcmp(dst, &ro->ro_dst, dst->sa_len) == 0) {
diff -urN sys/netkey/key.h sys.CORE/netkey/key.h
--- sys/netkey/key.h	Wed Jan 31 15:57:05 2007
+++ sys.CORE/netkey/key.h	Wed Jan 31 16:02:43 2007
@@ -35,7 +35,7 @@
 
 #ifdef _KERNEL
 
-extern struct key_cb key_cb;
+/*extern struct key_cb key_cb;*/
 
 struct secpolicy;
 struct secpolicyindex;
@@ -46,14 +46,15 @@
 struct sadb_msg;
 struct sadb_x_policy;
 
-extern struct secpolicy *key_allocsp __P((struct secpolicyindex *, u_int));
+extern struct secpolicy *key_allocsp __P((struct secpolicyindex *, u_int,
+	struct vnet*));
 extern struct secpolicy *key_gettunnel __P((struct sockaddr *,
-	struct sockaddr *, struct sockaddr *, struct sockaddr *));
+	struct sockaddr *, struct sockaddr *, struct sockaddr *, struct vnet*));
 extern int key_checkrequest
 	__P((struct ipsecrequest *isr, struct secasindex *,
 		struct vnet *));
 extern struct secasvar *key_allocsa __P((u_int, caddr_t, caddr_t,
-					u_int, u_int32_t));
+					u_int, u_int32_t, struct vnet *));
 extern void key_freesp __P((struct secpolicy *));
 extern void key_freeso __P((struct socket *));
 extern void key_freesav __P((struct secasvar *));
@@ -68,11 +69,12 @@
 extern void key_randomfill __P((void *, size_t));
 extern void key_freereg __P((struct socket *));
 extern int key_parse __P((struct mbuf *, struct socket *));
-extern void key_init __P((void));
+extern void key_init __P((struct vnet *));
+extern void key_destroy __P((struct vnet *));
 extern int key_checktunnelsanity __P((struct secasvar *, u_int,
 					caddr_t, caddr_t));
 extern void key_sa_recordxfer __P((struct secasvar *, struct mbuf *));
-extern void key_sa_routechange __P((struct sockaddr *));
+extern void key_sa_routechange __P((struct sockaddr *, struct vnet *));
 extern void key_sa_stir_iv __P((struct secasvar *));
 
 #ifdef MALLOC_DECLARE
diff -urN sys/netkey/keysock.c sys.CORE/netkey/keysock.c
--- sys/netkey/keysock.c	Wed Jan 31 15:57:05 2007
+++ sys.CORE/netkey/keysock.c	Wed Jan 31 16:02:43 2007
@@ -65,9 +65,7 @@
 struct sockaddr key_dst = { 2, PF_KEY, };
 struct sockaddr key_src = { 2, PF_KEY, };
 
-static int key_sendup0 __P((struct rawcb *, struct mbuf *, int));
-
-struct pfkeystat pfkeystat;
+static int key_sendup0 __P((struct rawcb *, struct mbuf *, int, struct vnet*));
 
 /*
  * key_output()
@@ -86,27 +84,31 @@
 	int s;
 	struct socket *so;
 	va_list ap;
+	struct vnet *vnet;
 
 	va_start(ap, m);
 	so = va_arg(ap, struct socket *);
+	vnet = va_arg(ap, struct vnet *);
 	va_end(ap);
 
 	if (m == 0)
 		panic("key_output: NULL pointer was passed.\n");
+	if (vnet == NULL)
+		panic("key_output: NULL vnet was passed.\n");
 
-	pfkeystat.out_total++;
-	pfkeystat.out_bytes += m->m_pkthdr.len;
+	vnet->pfkeystat.out_total++;
+	vnet->pfkeystat.out_bytes += m->m_pkthdr.len;
 
 	len = m->m_pkthdr.len;
 	if (len < sizeof(struct sadb_msg)) {
-		pfkeystat.out_tooshort++;
+		vnet->pfkeystat.out_tooshort++;
 		error = EINVAL;
 		goto end;
 	}
 
 	if (m->m_len < sizeof(struct sadb_msg)) {
 		if ((m = m_pullup(m, sizeof(struct sadb_msg))) == 0) {
-			pfkeystat.out_nomem++;
+			vnet->pfkeystat.out_nomem++;
 			error = ENOBUFS;
 			goto end;
 		}
@@ -118,9 +120,9 @@
 	KEYDEBUG(KEYDEBUG_KEY_DUMP, kdebug_mbuf(m));
 
 	msg = mtod(m, struct sadb_msg *);
-	pfkeystat.out_msgtype[msg->sadb_msg_type]++;
+	vnet->pfkeystat.out_msgtype[msg->sadb_msg_type]++;
 	if (len != PFKEY_UNUNIT64(msg->sadb_msg_len)) {
-		pfkeystat.out_invlen++;
+		vnet->pfkeystat.out_invlen++;
 		error = EINVAL;
 		goto end;
 	}
@@ -140,13 +142,17 @@
  * send message to the socket.
  */
 static int
-key_sendup0(rp, m, promisc)
+key_sendup0(rp, m, promisc, vnet)
 	struct rawcb *rp;
 	struct mbuf *m;
 	int promisc;
+	struct vnet *vnet;
 {
 	int error;
 
+	if (vnet == NULL)
+		panic("key_sendup0: NULL vnet was passed.\n");
+
 	if (promisc) {
 		struct sadb_msg *pmsg;
 
@@ -154,7 +160,7 @@
 		if (m && m->m_len < sizeof(struct sadb_msg))
 			m = m_pullup(m, sizeof(struct sadb_msg));
 		if (!m) {
-			pfkeystat.in_nomem++;
+			vnet->pfkeystat.in_nomem++;
 			m_freem(m);
 			return ENOBUFS;
 		}
@@ -167,12 +173,12 @@
 		pmsg->sadb_msg_len = PFKEY_UNIT64(m->m_pkthdr.len);
 		/* pid and seq? */
 
-		pfkeystat.in_msgtype[pmsg->sadb_msg_type]++;
+		vnet->pfkeystat.in_msgtype[pmsg->sadb_msg_type]++;
 	}
 
 	if (!sbappendaddr(&rp->rcb_socket->so_rcv, (struct sockaddr *)&key_src,
 	    m, NULL)) {
-		pfkeystat.in_nomem++;
+		vnet->pfkeystat.in_nomem++;
 		m_freem(m);
 		error = ENOBUFS;
 	} else
@@ -196,6 +202,8 @@
 	/* sanity check */
 	if (so == 0 || msg == 0)
 		panic("key_sendup: NULL pointer was passed.\n");
+	if (vnet == NULL)
+		panic("key_sendup: NULL vnet was passed.\n");
 
 	KEYDEBUG(KEYDEBUG_KEY_DUMP,
 		printf("key_sendup: \n");
@@ -205,9 +213,9 @@
 	 * we increment statistics here, just in case we have ENOBUFS
 	 * in this function.
 	 */
-	pfkeystat.in_total++;
-	pfkeystat.in_bytes += len;
-	pfkeystat.in_msgtype[msg->sadb_msg_type]++;
+	vnet->pfkeystat.in_total++;
+	vnet->pfkeystat.in_bytes += len;
+	vnet->pfkeystat.in_msgtype[msg->sadb_msg_type]++;
 
 	/*
 	 * Get mbuf chain whenever possible (not clusters),
@@ -229,7 +237,7 @@
 			n->m_len = MLEN;
 		}
 		if (!n) {
-			pfkeystat.in_nomem++;
+			vnet->pfkeystat.in_nomem++;
 			return ENOBUFS;
 		}
 		if (tlen >= MCLBYTES) {	/*XXX better threshold? */
@@ -237,7 +245,7 @@
 			if ((n->m_flags & M_EXT) == 0) {
 				m_free(n);
 				m_freem(m);
-				pfkeystat.in_nomem++;
+				vnet->pfkeystat.in_nomem++;
 				return ENOBUFS;
 			}
 			n->m_len = MCLBYTES;
@@ -260,9 +268,9 @@
 	m_copyback(m, 0, len, (caddr_t)msg);
 
 	/* avoid duplicated statistics */
-	pfkeystat.in_total--;
-	pfkeystat.in_bytes -= len;
-	pfkeystat.in_msgtype[msg->sadb_msg_type]--;
+	vnet->pfkeystat.in_total--;
+	vnet->pfkeystat.in_bytes -= len;
+	vnet->pfkeystat.in_msgtype[msg->sadb_msg_type]--;
 
 	return key_sendup_mbuf(so, m, target, vnet);
 }
@@ -285,14 +293,16 @@
 		panic("key_sendup_mbuf: NULL pointer was passed.\n");
 	if (so == NULL && target == KEY_SENDUP_ONE)
 		panic("key_sendup_mbuf: NULL pointer was passed.\n");
+	if (vnet == NULL)
+		panic("key_sendup_mbuf: NULL vnet pointer was passed.\n");
 
-	pfkeystat.in_total++;
-	pfkeystat.in_bytes += m->m_pkthdr.len;
+	vnet->pfkeystat.in_total++;
+	vnet->pfkeystat.in_bytes += m->m_pkthdr.len;
 	if (m->m_len < sizeof(struct sadb_msg)) {
 #if 1
 		m = m_pullup(m, sizeof(struct sadb_msg));
 		if (m == NULL) {
-			pfkeystat.in_nomem++;
+			vnet->pfkeystat.in_nomem++;
 			return ENOBUFS;
 		}
 #else
@@ -302,7 +312,7 @@
 	if (m->m_len >= sizeof(struct sadb_msg)) {
 		struct sadb_msg *msg;
 		msg = mtod(m, struct sadb_msg *);
-		pfkeystat.in_msgtype[msg->sadb_msg_type]++;
+		vnet->pfkeystat.in_msgtype[msg->sadb_msg_type]++;
 	}
 
 	LIST_FOREACH(rp, &vnet->rawcb_list, list)
@@ -323,7 +333,7 @@
 		 */
 		if (((struct keycb *)rp)->kp_promisc) {
 			if ((n = m_copy(m, 0, (int)M_COPYALL)) != NULL) {
-				(void)key_sendup0(rp, n, 1);
+				(void)key_sendup0(rp, n, 1, vnet);
 				n = NULL;
 			}
 		}
@@ -347,18 +357,18 @@
 				sendup++;
 			break;
 		}
-		pfkeystat.in_msgtarget[target]++;
+		vnet->pfkeystat.in_msgtarget[target]++;
 
 		if (!sendup)
 			continue;
 
 		if ((n = m_copy(m, 0, (int)M_COPYALL)) == NULL) {
 			m_freem(m);
-			pfkeystat.in_nomem++;
+			vnet->pfkeystat.in_nomem++;
 			return ENOBUFS;
 		}
 
-		if ((error = key_sendup0(rp, n, 0)) != 0) {
+		if ((error = key_sendup0(rp, n, 0, vnet)) != 0) {
 			m_freem(m);
 			return error;
 		}
@@ -367,7 +377,7 @@
 	}
 
 	if (so) {
-		error = key_sendup0(sotorawcb(so), m, 0);
+		error = key_sendup0(sotorawcb(so), m, 0, vnet);
 		m = NULL;
 	} else {
 		error = 0;
@@ -397,9 +407,12 @@
 static int
 key_attach(struct socket *so, int proto, struct proc *p)
 {
+	struct vnet *vnet = so->so_vnet;
 	struct keycb *kp;
 	int s, error;
 
+	if (vnet == NULL)
+		panic("key_attach: NULL vnet was passed.\n");
 	if (sotorawcb(so) != 0)
 		return EISCONN;	/* XXX panic? */
 	kp = (struct keycb *)malloc(sizeof *kp, M_PCB, M_WAITOK); /* XXX */
@@ -428,8 +441,8 @@
 	kp->kp_promisc = kp->kp_registered = 0;
 
 	if (kp->kp_raw.rcb_proto.sp_protocol == PF_KEY) /* XXX: AF_KEY */
-		key_cb.key_count++;
-	key_cb.any_count++;
+		vnet->key_cb.key_count++;
+	vnet->key_cb.any_count++;
 	kp->kp_raw.rcb_laddr = &key_src;
 	kp->kp_raw.rcb_faddr = &key_dst;
 	soisconnected(so);
@@ -474,15 +487,18 @@
 static int
 key_detach(struct socket *so)
 {
+	struct vnet *vnet = so->so_vnet;
 	struct keycb *kp = (struct keycb *)sotorawcb(so);
 	int s, error;
 
+	if (vnet == NULL)
+		panic("key_detach: NULL vnet from sock.");
 	s = splnet();
 	if (kp != 0) {
 		if (kp->kp_raw.rcb_proto.sp_protocol
 		    == PF_KEY) /* XXX: AF_KEY */
-			key_cb.key_count--;
-		key_cb.any_count--;
+			vnet->key_cb.key_count--;
+		vnet->key_cb.any_count--;
 
 		key_freereg(so);
 	}
@@ -585,13 +601,13 @@
 { SOCK_RAW,	&keydomain,	PF_KEY_V2,	PR_ATOMIC|PR_ADDR,
   0,		key_output,	raw_ctlinput,	0,
   0,
-  raw_init,	0,		0,		0,
+  raw_init,	raw_destroy,	0,		0,		0,
   &key_usrreqs
 }
 };
 
 struct domain keydomain =
-    { PF_KEY, "key", key_init, 0, 0,
+    { PF_KEY, "key", key_init, key_destroy, 0, 0,
       keysw, &keysw[sizeof(keysw)/sizeof(keysw[0])] };
 
 DOMAIN_SET(key);
diff -urN sys/netkey/keysock.h sys.CORE/netkey/keysock.h
--- sys/netkey/keysock.h	Wed Jan 31 15:57:05 2007
+++ sys.CORE/netkey/keysock.h	Wed Jan 31 16:02:43 2007
@@ -69,8 +69,6 @@
 	int kp_registered;	/* registered socket */
 };
 
-extern struct pfkeystat pfkeystat;
-
 extern int key_output __P((struct mbuf *, ...));
 extern int key_usrreq __P((struct socket *,
 	int, struct mbuf *, struct mbuf *, struct mbuf *));