Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 6 Nov 2008 08:25:14 -0800
From:      "Ahrenholz, Jeffrey M" <jeffrey.m.ahrenholz@boeing.com>
To:        <freebsd-virtualization@freebsd.org>
Subject:   multicast routing patch revised
Message-ID:  <0DF156EE7414494187B087A3C279BDB40AF14C23@XCH-NW-6V1.nw.nos.boeing.com>

index | next in thread | raw e-mail

[-- Attachment #1 --]
Hi,
Attached is an updated patch for multicast routing. This is against the
vimage_7-20081015.tgz that Marko has posted on http://imunes.tel.fer.hr/

This fixes a number of issues with the previous patch that I posted -
initialization problems, adds IPv6 multicast routing support, fixes
timer functions with the bandwidth monitoring code. This has been tested
with PIM and IPv4 and IPv6 multicast routing. Now it uses its own
VNET_MOD_MROUTE state allowing for proper initialization.

The file porting_to_vimage.txt has been very helpful! I still have one
problem however which is not covered by the text -- when you
reboot/shutdown the machine, the ip_mroute_modevent() w/MOD_UNLOAD is
called without curvnet being valid. How do you find the proper vnet in
this situation?

-Jeff

[-- Attachment #2 --]
diff -ur sys.20081015/netinet/ip_mroute.c sys/netinet/ip_mroute.c
--- sys.20081015/netinet/ip_mroute.c	2008-08-16 16:29:19.000000000 -0700
+++ sys/netinet/ip_mroute.c	2008-11-05 16:30:04.000000000 -0800
@@ -99,6 +99,7 @@
 #include <netinet/pim_var.h>
 #include <netinet/udp.h>
 #ifdef INET6
+#include <netinet6/vinet6.h>
 #include <netinet/ip6.h>
 #include <netinet6/in6_var.h>
 #include <netinet6/ip6_mroute.h>
@@ -112,21 +113,30 @@
  * Control debugging code for rsvp and multicast routing code.
  * Can only set them with the debugger.
  */
+#ifndef VIMAGE
 static u_int    rsvpdebug;		/* non-zero enables debugging	*/
 
 static u_int	mrtdebug;		/* any set of the flags below	*/
+#endif /* !VIMAGE */
 #define		DEBUG_MFC	0x02
 #define		DEBUG_FORWARD	0x04
 #define		DEBUG_EXPIRE	0x08
 #define		DEBUG_XMIT	0x10
 #define		DEBUG_PIM	0x20
 
+#ifndef VIMAGE
 #define		VIFI_INVALID	((vifi_t) -1)
+#endif /* !VIMAGE */
 
 #define M_HASCL(m)	((m)->m_flags & M_EXT)
 
 static MALLOC_DEFINE(M_MRTABLE, "mroutetbl", "multicast routing tables");
 
+static int vnet_mroute_iattach(const void *);
+static int vnet_mroute_idetach(const void *);
+
+VNET_MOD_DECLARE(MROUTE, mroute, vnet_mroute_iattach, vnet_mroute_idetach, INET, NULL)
+
 /*
  * Locking.  We use two locks: one for the virtual interface table and
  * one for the forwarding table.  These locks may be nested in which case
@@ -140,48 +150,59 @@
  *
  */
 
+#ifndef VIMAGE
 static struct mrtstat	mrtstat;
-SYSCTL_STRUCT(_net_inet_ip, OID_AUTO, mrtstat, CTLFLAG_RW,
-    &mrtstat, mrtstat,
+#endif /* !VIMAGE */
+SYSCTL_V_STRUCT(V_NET, vnet_mroute, _net_inet_ip, OID_AUTO, mrtstat,
+    CTLFLAG_RW, mrtstat, mrtstat,
     "Multicast Routing Statistics (struct mrtstat, netinet/ip_mroute.h)");
-
+#ifndef VIMAGE
 static struct mfc	*mfctable[MFCTBLSIZ];
-SYSCTL_OPAQUE(_net_inet_ip, OID_AUTO, mfctable, CTLFLAG_RD,
-    &mfctable, sizeof(mfctable), "S,*mfc[MFCTBLSIZ]",
+SYSCTL_V_OID(V_NET, vnet_mroute, _net_inet_ip, CTLTYPE_OPAQUE|OID_AUTO,
+    mfctable, CTLFLAG_RD, mfctable, sizeof(mfctable), sysctl_handle_opaque,
+    "S,*mfc[MFCTBLSIZ]",
     "Multicast Forwarding Table (struct *mfc[MFCTBLSIZ], netinet/ip_mroute.h)");
 
 static struct mtx mrouter_mtx;
-#define	MROUTER_LOCK()		mtx_lock(&mrouter_mtx)
-#define	MROUTER_UNLOCK()	mtx_unlock(&mrouter_mtx)
-#define	MROUTER_LOCK_ASSERT()	mtx_assert(&mrouter_mtx, MA_OWNED)
+#endif /* !VIMAGE */
+#define	MROUTER_LOCK()		mtx_lock(&V_mrouter_mtx)
+#define	MROUTER_UNLOCK()	mtx_unlock(&V_mrouter_mtx)
+#define	MROUTER_LOCK_ASSERT()	mtx_assert(&V_mrouter_mtx, MA_OWNED)
 #define	MROUTER_LOCK_INIT()	\
-	mtx_init(&mrouter_mtx, "IPv4 multicast forwarding", NULL, MTX_DEF)
-#define	MROUTER_LOCK_DESTROY()	mtx_destroy(&mrouter_mtx)
+	mtx_init(&V_mrouter_mtx, "IPv4 multicast forwarding", NULL, MTX_DEF)
+#define	MROUTER_LOCK_DESTROY()	mtx_destroy(&V_mrouter_mtx)
 
+#ifndef VIMAGE
 static struct mtx mfc_mtx;
-#define	MFC_LOCK()	mtx_lock(&mfc_mtx)
-#define	MFC_UNLOCK()	mtx_unlock(&mfc_mtx)
-#define	MFC_LOCK_ASSERT()	mtx_assert(&mfc_mtx, MA_OWNED)
-#define	MFC_LOCK_INIT()	mtx_init(&mfc_mtx, "mroute mfc table", NULL, MTX_DEF)
-#define	MFC_LOCK_DESTROY()	mtx_destroy(&mfc_mtx)
+#endif /* !VIMAGE */
+#define	MFC_LOCK()	mtx_lock(&V_mfc_mtx)
+#define	MFC_UNLOCK()	mtx_unlock(&V_mfc_mtx)
+#define	MFC_LOCK_ASSERT()	mtx_assert(&V_mfc_mtx, MA_OWNED)
+#define	MFC_LOCK_INIT()	mtx_init(&V_mfc_mtx, "mroute mfc table", NULL, MTX_DEF)
+#define	MFC_LOCK_DESTROY()	mtx_destroy(&V_mfc_mtx)
 
+#ifndef VIMAGE
 static struct vif	viftable[MAXVIFS];
-SYSCTL_OPAQUE(_net_inet_ip, OID_AUTO, viftable, CTLFLAG_RD,
-    &viftable, sizeof(viftable), "S,vif[MAXVIFS]",
+SYSCTL_V_OID(V_NET, vnet_mroute, _net_inet_ip, CTLTYPE_OPAQUE|OID_AUTO, viftable,
+    CTLFLAG_RD, viftable, sizeof(viftable), sysctl_handle_opaque, 
+    "S,vif[MAXVIFS]",
     "Multicast Virtual Interfaces (struct vif[MAXVIFS], netinet/ip_mroute.h)");
 
 static struct mtx vif_mtx;
-#define	VIF_LOCK()	mtx_lock(&vif_mtx)
-#define	VIF_UNLOCK()	mtx_unlock(&vif_mtx)
-#define	VIF_LOCK_ASSERT()	mtx_assert(&vif_mtx, MA_OWNED)
-#define	VIF_LOCK_INIT()	mtx_init(&vif_mtx, "mroute vif table", NULL, MTX_DEF)
-#define	VIF_LOCK_DESTROY()	mtx_destroy(&vif_mtx)
+#endif /* !VIMAGE */
+#define	VIF_LOCK()	mtx_lock(&V_vif_mtx)
+#define	VIF_UNLOCK()	mtx_unlock(&V_vif_mtx)
+#define	VIF_LOCK_ASSERT()	mtx_assert(&V_vif_mtx, MA_OWNED)
+#define	VIF_LOCK_INIT()	mtx_init(&V_vif_mtx, "mroute vif table", NULL, MTX_DEF)
+#define	VIF_LOCK_DESTROY()	mtx_destroy(&V_vif_mtx)
 
+#ifndef VIMAGE
 static u_char		nexpire[MFCTBLSIZ];
 
 static eventhandler_tag if_detach_event_tag = NULL;
 
 static struct callout expire_upcalls_ch;
+#endif /* !VIMAGE */
 
 #define		EXPIRE_TIMEOUT	(hz / 4)	/* 4x / second		*/
 #define		UPCALL_EXPIRE	6		/* number of timeouts	*/
@@ -196,25 +217,31 @@
  * Pending timeouts are stored in a hash table, the key being the
  * expiration time. Periodically, the entries are analysed and processed.
  */
+#ifndef VIMAGE
 #define BW_METER_BUCKETS	1024
 static struct bw_meter *bw_meter_timers[BW_METER_BUCKETS];
-static struct callout bw_meter_ch;
+static struct callout V_bw_meter_ch;
+#endif /* !VIMAGE */
 #define BW_METER_PERIOD (hz)		/* periodical handling of bw meters */
 
 /*
  * Pending upcalls are stored in a vector which is flushed when
  * full, or periodically
  */
+#ifndef VIMAGE
 static struct bw_upcall	bw_upcalls[BW_UPCALLS_MAX];
 static u_int	bw_upcalls_n; /* # of pending upcalls */
 static struct callout bw_upcalls_ch;
+#endif /* !VIMAGE */
 #define BW_UPCALLS_PERIOD (hz)		/* periodical flush of bw upcalls */
 
+#ifndef VIMAGE
 static struct pimstat pimstat;
+#endif /* !VIMAGE */
 
 SYSCTL_NODE(_net_inet, IPPROTO_PIM, pim, CTLFLAG_RW, 0, "PIM");
-SYSCTL_STRUCT(_net_inet_pim, PIMCTL_STATS, stats, CTLFLAG_RD,
-    &pimstat, pimstat,
+SYSCTL_V_STRUCT(V_NET, vnet_mroute, _net_inet_pim, PIMCTL_STATS, stats,
+    CTLFLAG_RD, pimstat, pimstat,
     "PIM Statistics (struct pimstat, netinet/pim_var.h)");
 
 static u_long	pim_squelch_wholepkt = 0;
@@ -222,6 +249,7 @@
     &pim_squelch_wholepkt, 0,
     "Disable IGMP_WHOLEPKT notifications if rendezvous point is unspecified");
 
+
 extern  struct domain inetdomain;
 struct protosw in_pim_protosw = {
 	.pr_type =		SOCK_RAW,
@@ -291,13 +319,17 @@
     0				/* flags */
 };
 
+#ifndef VIMAGE
 static struct ifnet multicast_register_if;
 static vifi_t reg_vif_num = VIFI_INVALID;
+#endif /* !VIMAGE */
 
 /*
  * Private variables.
  */
+#ifndef VIMAGE
 static vifi_t	   numvifs;
+#endif /* !VIMAGE */
 
 static u_long	X_ip_mcast_src(int vifi);
 static int	X_ip_mforward(struct ip *ip, struct ifnet *ifp,
@@ -337,7 +369,7 @@
 static void bw_upcalls_send(void);
 static void schedule_bw_meter(struct bw_meter *x, struct timeval *nowp);
 static void unschedule_bw_meter(struct bw_meter *x);
-static void bw_meter_process(void);
+static void bw_meter_process(struct vnet *vnet);
 static void expire_bw_upcalls_send(void *);
 static void expire_bw_meter_process(void *);
 
@@ -352,7 +384,9 @@
 /*
  * whether or not special PIM assert processing is enabled.
  */
+#ifndef VIMAGE
 static int pim_assert;
+#endif /* !VIMAGE */
 /*
  * Rate limit for assert notification messages, in usec
  */
@@ -367,7 +401,9 @@
 					 MRT_MFC_FLAGS_BORDER_VIF |
 					 MRT_MFC_RP |
 					 MRT_MFC_BW_UPCALL);
+#ifndef VIMAGE
 static uint32_t mrt_api_config = 0;
+#endif /* !VIMAGE */
 
 /*
  * Hash function for a source, group entry
@@ -383,11 +419,12 @@
 static struct mfc *
 mfc_find(in_addr_t o, in_addr_t g)
 {
+    INIT_VNET_MROUTE(curvnet);
     struct mfc *rt;
 
     MFC_LOCK_ASSERT();
 
-    for (rt = mfctable[MFCHASH(o,g)]; rt; rt = rt->mfc_next)
+    for (rt = V_mfctable[MFCHASH(o,g)]; rt; rt = rt->mfc_next)
 	if ((rt->mfc_origin.s_addr == o) &&
 		(rt->mfc_mcastgrp.s_addr == g) && (rt->mfc_stall == NULL))
 	    break;
@@ -424,7 +461,8 @@
 static int
 X_ip_mrouter_set(struct socket *so, struct sockopt *sopt)
 {
-    INIT_VNET_INET(curvnet);
+    INIT_VNET_INET(so->so_vnet);
+    INIT_VNET_MROUTE(so->so_vnet);
     int	error, optval;
     vifi_t	vifi;
     struct	vifctl vifc;
@@ -468,7 +506,7 @@
 	 * select data size depending on API version.
 	 */
 	if (sopt->sopt_name == MRT_ADD_MFC &&
-		mrt_api_config & MRT_API_FLAGS_ALL) {
+		V_mrt_api_config & MRT_API_FLAGS_ALL) {
 	    error = sooptcopyin(sopt, &mfc, sizeof(struct mfcctl2),
 				sizeof(struct mfcctl2));
 	} else {
@@ -525,6 +563,7 @@
 static int
 X_ip_mrouter_get(struct socket *so, struct sockopt *sopt)
 {
+    INIT_VNET_MROUTE(so->so_vnet);
     int error;
     static int version = 0x0305; /* !!! why is this here? XXX */
 
@@ -534,7 +573,7 @@
 	break;
 
     case MRT_ASSERT:
-	error = sooptcopyout(sopt, &pim_assert, sizeof pim_assert);
+	error = sooptcopyout(sopt, &V_pim_assert, sizeof V_pim_assert);
 	break;
 
     case MRT_API_SUPPORT:
@@ -542,7 +581,7 @@
 	break;
 
     case MRT_API_CONFIG:
-	error = sooptcopyout(sopt, &mrt_api_config, sizeof mrt_api_config);
+	error = sooptcopyout(sopt, &V_mrt_api_config, sizeof V_mrt_api_config);
 	break;
 
     default:
@@ -590,6 +629,7 @@
 static int
 get_sg_cnt(struct sioc_sg_req *req)
 {
+    INIT_VNET_MROUTE(curvnet);
     struct mfc *rt;
 
     MFC_LOCK();
@@ -612,18 +652,19 @@
 static int
 get_vif_cnt(struct sioc_vif_req *req)
 {
+    INIT_VNET_MROUTE(curvnet);
     vifi_t vifi = req->vifi;
 
     VIF_LOCK();
-    if (vifi >= numvifs) {
+    if (vifi >= V_numvifs) {
 	VIF_UNLOCK();
 	return EINVAL;
     }
 
-    req->icount = viftable[vifi].v_pkt_in;
-    req->ocount = viftable[vifi].v_pkt_out;
-    req->ibytes = viftable[vifi].v_bytes_in;
-    req->obytes = viftable[vifi].v_bytes_out;
+    req->icount = V_viftable[vifi].v_pkt_in;
+    req->ocount = V_viftable[vifi].v_pkt_out;
+    req->ibytes = V_viftable[vifi].v_bytes_in;
+    req->obytes = V_viftable[vifi].v_bytes_out;
     VIF_UNLOCK();
 
     return 0;
@@ -632,24 +673,30 @@
 static void
 ip_mrouter_reset(void)
 {
-    bzero((caddr_t)mfctable, sizeof(mfctable));
-    bzero((caddr_t)nexpire, sizeof(nexpire));
-
-    pim_assert = 0;
-    mrt_api_config = 0;
-
-    callout_init(&expire_upcalls_ch, CALLOUT_MPSAFE);
-
-    bw_upcalls_n = 0;
-    bzero((caddr_t)bw_meter_timers, sizeof(bw_meter_timers));
-    callout_init(&bw_upcalls_ch, CALLOUT_MPSAFE);
-    callout_init(&bw_meter_ch, CALLOUT_MPSAFE);
+    INIT_VNET_MROUTE(curvnet);
+    bzero((caddr_t)V_mfctable, sizeof(V_mfctable));
+    bzero((caddr_t)V_nexpire, sizeof(V_nexpire));
+    if (V_reg_vif_num != VIFI_INVALID)
+	IF_ADDR_LOCK_DESTROY(&V_multicast_register_if);
+    bzero(&V_multicast_register_if, sizeof(V_multicast_register_if));
+
+    V_reg_vif_num = VIFI_INVALID;
+    V_pim_assert = 0;
+    V_mrt_api_config = 0;
+    
+    callout_init(&V_expire_upcalls_ch, CALLOUT_MPSAFE);
+
+    V_bw_upcalls_n = 0;
+    bzero((caddr_t)V_bw_meter_timers, sizeof(V_bw_meter_timers));
+    callout_init(&V_bw_upcalls_ch, CALLOUT_MPSAFE);
+    callout_init(&V_bw_meter_ch, CALLOUT_MPSAFE);
 }
 
 static void
 if_detached_event(void *arg __unused, struct ifnet *ifp)
 {
     INIT_VNET_INET(curvnet);
+    INIT_VNET_MROUTE(curvnet);
     vifi_t vifi;
     int i;
     struct mfc *mfc;
@@ -676,12 +723,12 @@
      */
     VIF_LOCK();
     MFC_LOCK();
-    for (vifi = 0; vifi < numvifs; vifi++) {
-	if (viftable[vifi].v_ifp != ifp)
+    for (vifi = 0; vifi < V_numvifs; vifi++) {
+	if (V_viftable[vifi].v_ifp != ifp)
 		continue;
 	for (i = 0; i < MFCTBLSIZ; i++) {
-	    ppmfc = &mfctable[i];
-	    for (mfc = mfctable[i]; mfc != NULL; ) {
+	    ppmfc = &V_mfctable[i];
+	    for (mfc = V_mfctable[i]; mfc != NULL; ) {
 		nmfc = mfc->mfc_next;
 		if (mfc->mfc_parent == vifi) {
 		    for (pq = mfc->mfc_stall; pq != NULL; ) {
@@ -713,9 +760,10 @@
 static int
 ip_mrouter_init(struct socket *so, int version)
 {
-    INIT_VNET_INET(curvnet);
+    INIT_VNET_INET(so->so_vnet);
+    INIT_VNET_MROUTE(so->so_vnet);
 
-    if (mrtdebug)
+    if (V_mrtdebug)
 	log(LOG_DEBUG, "ip_mrouter_init: so_type = %d, pr_protocol = %d\n",
 	    so->so_type, so->so_proto->pr_protocol);
 
@@ -732,24 +780,25 @@
 	return EADDRINUSE;
     }
 
-    if_detach_event_tag = EVENTHANDLER_REGISTER(ifnet_departure_event, 
+    V_if_detach_event_tag = EVENTHANDLER_REGISTER(ifnet_departure_event, 
         if_detached_event, NULL, EVENTHANDLER_PRI_ANY);
-    if (if_detach_event_tag == NULL) {
+    if (V_if_detach_event_tag == NULL) {
 	MROUTER_UNLOCK();
 	return (ENOMEM);
     }
 
-    callout_reset(&expire_upcalls_ch, EXPIRE_TIMEOUT, expire_upcalls, NULL);
-
-    callout_reset(&bw_upcalls_ch, BW_UPCALLS_PERIOD,
-	expire_bw_upcalls_send, NULL);
-    callout_reset(&bw_meter_ch, BW_METER_PERIOD, expire_bw_meter_process, NULL);
+    callout_reset(&V_expire_upcalls_ch, EXPIRE_TIMEOUT,
+		expire_upcalls, (void *)so->so_vnet);
+    callout_reset(&V_bw_upcalls_ch, BW_UPCALLS_PERIOD,
+		expire_bw_upcalls_send, (void *)so->so_vnet);
+    callout_reset(&V_bw_meter_ch, BW_METER_PERIOD,
+		expire_bw_meter_process, (void *)so->so_vnet);
 
     V_ip_mrouter = so;
 
     MROUTER_UNLOCK();
 
-    if (mrtdebug)
+    if (V_mrtdebug)
 	log(LOG_DEBUG, "ip_mrouter_init\n");
 
     return 0;
@@ -762,6 +811,7 @@
 X_ip_mrouter_done(void)
 {
     INIT_VNET_INET(curvnet);
+    INIT_VNET_MROUTE(curvnet);
     vifi_t vifi;
     int i;
     struct ifnet *ifp;
@@ -780,41 +830,41 @@
      * Detach/disable hooks to the reset of the system.
      */
     V_ip_mrouter = NULL;
-    mrt_api_config = 0;
+    V_mrt_api_config = 0;
 
     VIF_LOCK();
     /*
      * For each phyint in use, disable promiscuous reception of all IP
      * multicasts.
      */
-    for (vifi = 0; vifi < numvifs; vifi++) {
-	if (viftable[vifi].v_lcl_addr.s_addr != 0 &&
-		!(viftable[vifi].v_flags & (VIFF_TUNNEL | VIFF_REGISTER))) {
+    for (vifi = 0; vifi < V_numvifs; vifi++) {
+	if (V_viftable[vifi].v_lcl_addr.s_addr != 0 &&
+		!(V_viftable[vifi].v_flags & (VIFF_TUNNEL | VIFF_REGISTER))) {
 	    struct sockaddr_in *so = (struct sockaddr_in *)&(ifr.ifr_addr);
 
 	    so->sin_len = sizeof(struct sockaddr_in);
 	    so->sin_family = AF_INET;
 	    so->sin_addr.s_addr = INADDR_ANY;
-	    ifp = viftable[vifi].v_ifp;
+	    ifp = V_viftable[vifi].v_ifp;
 	    if_allmulti(ifp, 0);
 	}
     }
-    bzero((caddr_t)viftable, sizeof(viftable));
-    numvifs = 0;
-    pim_assert = 0;
+    bzero((caddr_t)V_viftable, sizeof(V_viftable));
+    V_numvifs = 0;
+    V_pim_assert = 0;
     VIF_UNLOCK();
-    EVENTHANDLER_DEREGISTER(ifnet_departure_event, if_detach_event_tag);
+    EVENTHANDLER_DEREGISTER(ifnet_departure_event, V_if_detach_event_tag);
 
     /*
      * Free all multicast forwarding cache entries.
      */
-    callout_stop(&expire_upcalls_ch);
-    callout_stop(&bw_upcalls_ch);
-    callout_stop(&bw_meter_ch);
+    callout_stop(&V_expire_upcalls_ch);
+    callout_stop(&V_bw_upcalls_ch);
+    callout_stop(&V_bw_meter_ch);
 
     MFC_LOCK();
     for (i = 0; i < MFCTBLSIZ; i++) {
-	for (rt = mfctable[i]; rt != NULL; ) {
+	for (rt = V_mfctable[i]; rt != NULL; ) {
 	    struct mfc *nr = rt->mfc_next;
 
 	    for (rte = rt->mfc_stall; rte != NULL; ) {
@@ -829,17 +879,19 @@
 	    rt = nr;
 	}
     }
-    bzero((caddr_t)mfctable, sizeof(mfctable));
-    bzero((caddr_t)nexpire, sizeof(nexpire));
-    bw_upcalls_n = 0;
-    bzero(bw_meter_timers, sizeof(bw_meter_timers));
+    bzero((caddr_t)V_mfctable, sizeof(V_mfctable));
+    bzero((caddr_t)V_nexpire, sizeof(V_nexpire));
+    V_bw_upcalls_n = 0;
+    bzero(V_bw_meter_timers, sizeof(V_bw_meter_timers));
     MFC_UNLOCK();
 
-    reg_vif_num = VIFI_INVALID;
+    if (V_reg_vif_num != VIFI_INVALID)
+	IF_ADDR_LOCK_DESTROY(&V_multicast_register_if);
+    V_reg_vif_num = VIFI_INVALID;
 
     MROUTER_UNLOCK();
 
-    if (mrtdebug)
+    if (V_mrtdebug)
 	log(LOG_DEBUG, "ip_mrouter_done\n");
 
     return 0;
@@ -851,10 +903,11 @@
 static int
 set_assert(int i)
 {
+    INIT_VNET_MROUTE(curvnet);
     if ((i != 1) && (i != 0))
 	return EINVAL;
 
-    pim_assert = i;
+    V_pim_assert = i;
 
     return 0;
 }
@@ -865,6 +918,7 @@
 int
 set_api_config(uint32_t *apival)
 {
+    INIT_VNET_MROUTE(curvnet);
     int i;
 
     /*
@@ -874,23 +928,23 @@
      *  - pim_assert is not enabled
      *  - the MFC table is empty
      */
-    if (numvifs > 0) {
+    if (V_numvifs > 0) {
 	*apival = 0;
 	return EPERM;
     }
-    if (pim_assert) {
+    if (V_pim_assert) {
 	*apival = 0;
 	return EPERM;
     }
     for (i = 0; i < MFCTBLSIZ; i++) {
-	if (mfctable[i] != NULL) {
+	if (V_mfctable[i] != NULL) {
 	    *apival = 0;
 	    return EPERM;
 	}
     }
 
-    mrt_api_config = *apival & mrt_api_support;
-    *apival = mrt_api_config;
+    V_mrt_api_config = *apival & mrt_api_support;
+    *apival = V_mrt_api_config;
 
     return 0;
 }
@@ -901,7 +955,8 @@
 static int
 add_vif(struct vifctl *vifcp)
 {
-    struct vif *vifp = viftable + vifcp->vifc_vifi;
+    INIT_VNET_MROUTE(curvnet);
+    struct vif *vifp = V_viftable + vifcp->vifc_vifi;
     struct sockaddr_in sin = {sizeof sin, AF_INET};
     struct ifaddr *ifa;
     struct ifnet *ifp;
@@ -950,14 +1005,19 @@
 	VIF_UNLOCK();
 	return EOPNOTSUPP;
     } else if (vifcp->vifc_flags & VIFF_REGISTER) {
-	ifp = &multicast_register_if;
-	if (mrtdebug)
+	ifp = &V_multicast_register_if;
+	if (V_mrtdebug)
 	    log(LOG_DEBUG, "Adding a register vif, ifp: %p\n",
-		    (void *)&multicast_register_if);
-	if (reg_vif_num == VIFI_INVALID) {
-	    if_initname(&multicast_register_if, "register_vif", 0);
-	    multicast_register_if.if_flags = IFF_LOOPBACK;
-	    reg_vif_num = vifcp->vifc_vifi;
+		    (void *)&V_multicast_register_if);
+	if (V_reg_vif_num == VIFI_INVALID) {
+	    if_initname(&V_multicast_register_if, "register_vif", 0);
+	    V_multicast_register_if.if_flags = IFF_LOOPBACK;
+	    V_reg_vif_num = vifcp->vifc_vifi;
+	    IF_ADDR_LOCK_INIT(&V_multicast_register_if);
+#ifdef VIMAGE
+	    V_multicast_register_if.if_vnet = curvnet;
+	    V_multicast_register_if.if_home_vnet = curvnet;
+#endif /* VIMAGE */
 	}
     } else {		/* Make sure the interface supports multicast */
 	if ((ifp->if_flags & IFF_MULTICAST) == 0) {
@@ -988,11 +1048,11 @@
     bzero(&vifp->v_route, sizeof(vifp->v_route));
 
     /* Adjust numvifs up if the vifi is higher than numvifs */
-    if (numvifs <= vifcp->vifc_vifi) numvifs = vifcp->vifc_vifi + 1;
+    if (V_numvifs <= vifcp->vifc_vifi) V_numvifs = vifcp->vifc_vifi + 1;
 
     VIF_UNLOCK();
 
-    if (mrtdebug)
+    if (V_mrtdebug)
 	log(LOG_DEBUG, "add_vif #%d, lcladdr %lx, %s %lx, thresh %x\n",
 	    vifcp->vifc_vifi,
 	    (u_long)ntohl(vifcp->vifc_lcl_addr.s_addr),
@@ -1009,14 +1069,15 @@
 static int
 del_vif_locked(vifi_t vifi)
 {
+    INIT_VNET_MROUTE(curvnet);
     struct vif *vifp;
 
     VIF_LOCK_ASSERT();
 
-    if (vifi >= numvifs) {
+    if (vifi >= V_numvifs) {
 	return EINVAL;
     }
-    vifp = &viftable[vifi];
+    vifp = &V_viftable[vifi];
     if (vifp->v_lcl_addr.s_addr == INADDR_ANY) {
 	return EADDRNOTAVAIL;
     }
@@ -1024,19 +1085,22 @@
     if (!(vifp->v_flags & (VIFF_TUNNEL | VIFF_REGISTER)))
 	if_allmulti(vifp->v_ifp, 0);
 
-    if (vifp->v_flags & VIFF_REGISTER)
-	reg_vif_num = VIFI_INVALID;
+    if (vifp->v_flags & VIFF_REGISTER) {
+	if (V_reg_vif_num != VIFI_INVALID)
+	    IF_ADDR_LOCK_DESTROY(&V_multicast_register_if);
+	V_reg_vif_num = VIFI_INVALID;
+    }
 
     bzero((caddr_t)vifp, sizeof (*vifp));
 
-    if (mrtdebug)
-	log(LOG_DEBUG, "del_vif %d, numvifs %d\n", vifi, numvifs);
+    if (V_mrtdebug)
+	log(LOG_DEBUG, "del_vif %d, numvifs %d\n", vifi, V_numvifs);
 
     /* Adjust numvifs down */
-    for (vifi = numvifs; vifi > 0; vifi--)
-	if (viftable[vifi-1].v_lcl_addr.s_addr != INADDR_ANY)
+    for (vifi = V_numvifs; vifi > 0; vifi--)
+	if (V_viftable[vifi-1].v_lcl_addr.s_addr != INADDR_ANY)
 	    break;
-    numvifs = vifi;
+    V_numvifs = vifi;
 
     return 0;
 }
@@ -1044,6 +1108,7 @@
 static int
 del_vif(vifi_t vifi)
 {
+    INIT_VNET_MROUTE(curvnet);
     int cc;
 
     VIF_LOCK();
@@ -1059,16 +1124,17 @@
 static void
 update_mfc_params(struct mfc *rt, struct mfcctl2 *mfccp)
 {
+    INIT_VNET_MROUTE(curvnet);
     int i;
 
     rt->mfc_parent = mfccp->mfcc_parent;
-    for (i = 0; i < numvifs; i++) {
+    for (i = 0; i < V_numvifs; i++) {
 	rt->mfc_ttls[i] = mfccp->mfcc_ttls[i];
-	rt->mfc_flags[i] = mfccp->mfcc_flags[i] & mrt_api_config &
+	rt->mfc_flags[i] = mfccp->mfcc_flags[i] & V_mrt_api_config &
 	    MRT_MFC_FLAGS_ALL;
     }
     /* set the RP address */
-    if (mrt_api_config & MRT_MFC_RP)
+    if (V_mrt_api_config & MRT_MFC_RP)
 	rt->mfc_rp = mfccp->mfcc_rp;
     else
 	rt->mfc_rp.s_addr = INADDR_ANY;
@@ -1099,6 +1165,7 @@
 static int
 add_mfc(struct mfcctl2 *mfccp)
 {
+    INIT_VNET_MROUTE(curvnet);
     struct mfc *rt;
     u_long hash;
     struct rtdetq *rte;
@@ -1111,7 +1178,7 @@
 
     /* If an entry already exists, just update the fields */
     if (rt) {
-	if (mrtdebug & DEBUG_MFC)
+	if (V_mrtdebug & DEBUG_MFC)
 	    log(LOG_DEBUG,"add_mfc update o %lx g %lx p %x\n",
 		(u_long)ntohl(mfccp->mfcc_origin.s_addr),
 		(u_long)ntohl(mfccp->mfcc_mcastgrp.s_addr),
@@ -1127,7 +1194,7 @@
      * Find the entry for which the upcall was made and update
      */
     hash = MFCHASH(mfccp->mfcc_origin.s_addr, mfccp->mfcc_mcastgrp.s_addr);
-    for (rt = mfctable[hash], nstl = 0; rt; rt = rt->mfc_next) {
+    for (rt = V_mfctable[hash], nstl = 0; rt; rt = rt->mfc_next) {
 
 	if ((rt->mfc_origin.s_addr == mfccp->mfcc_origin.s_addr) &&
 		(rt->mfc_mcastgrp.s_addr == mfccp->mfcc_mcastgrp.s_addr) &&
@@ -1140,7 +1207,7 @@
 		    (u_long)ntohl(mfccp->mfcc_mcastgrp.s_addr),
 		    mfccp->mfcc_parent, (void *)rt->mfc_stall);
 
-	    if (mrtdebug & DEBUG_MFC)
+	    if (V_mrtdebug & DEBUG_MFC)
 		log(LOG_DEBUG,"add_mfc o %lx g %lx p %x dbg %p\n",
 		    (u_long)ntohl(mfccp->mfcc_origin.s_addr),
 		    (u_long)ntohl(mfccp->mfcc_mcastgrp.s_addr),
@@ -1149,7 +1216,7 @@
 	    init_mfc_params(rt, mfccp);
 
 	    rt->mfc_expire = 0;	/* Don't clean this guy up */
-	    nexpire[hash]--;
+	    V_nexpire[hash]--;
 
 	    /* free packets Qed at the end of this entry */
 	    for (rte = rt->mfc_stall; rte != NULL; ) {
@@ -1168,18 +1235,18 @@
      * It is possible that an entry is being inserted without an upcall
      */
     if (nstl == 0) {
-	if (mrtdebug & DEBUG_MFC)
+	if (V_mrtdebug & DEBUG_MFC)
 	    log(LOG_DEBUG,"add_mfc no upcall h %lu o %lx g %lx p %x\n",
 		hash, (u_long)ntohl(mfccp->mfcc_origin.s_addr),
 		(u_long)ntohl(mfccp->mfcc_mcastgrp.s_addr),
 		mfccp->mfcc_parent);
 
-	for (rt = mfctable[hash]; rt != NULL; rt = rt->mfc_next) {
+	for (rt = V_mfctable[hash]; rt != NULL; rt = rt->mfc_next) {
 	    if ((rt->mfc_origin.s_addr == mfccp->mfcc_origin.s_addr) &&
 		    (rt->mfc_mcastgrp.s_addr == mfccp->mfcc_mcastgrp.s_addr)) {
 		init_mfc_params(rt, mfccp);
 		if (rt->mfc_expire)
-		    nexpire[hash]--;
+		    V_nexpire[hash]--;
 		rt->mfc_expire = 0;
 		break; /* XXX */
 	    }
@@ -1198,8 +1265,8 @@
 
 	    rt->mfc_bw_meter = NULL;
 	    /* insert new entry at head of hash chain */
-	    rt->mfc_next = mfctable[hash];
-	    mfctable[hash] = rt;
+	    rt->mfc_next = V_mfctable[hash];
+	    V_mfctable[hash] = rt;
 	}
     }
     MFC_UNLOCK();
@@ -1213,6 +1280,7 @@
 static int
 del_mfc(struct mfcctl2 *mfccp)
 {
+    INIT_VNET_MROUTE(curvnet);
     struct in_addr	origin;
     struct in_addr	mcastgrp;
     struct mfc		*rt;
@@ -1223,14 +1291,14 @@
     origin = mfccp->mfcc_origin;
     mcastgrp = mfccp->mfcc_mcastgrp;
 
-    if (mrtdebug & DEBUG_MFC)
+    if (V_mrtdebug & DEBUG_MFC)
 	log(LOG_DEBUG,"del_mfc orig %lx mcastgrp %lx\n",
 	    (u_long)ntohl(origin.s_addr), (u_long)ntohl(mcastgrp.s_addr));
 
     MFC_LOCK();
 
     hash = MFCHASH(origin.s_addr, mcastgrp.s_addr);
-    for (nptr = &mfctable[hash]; (rt = *nptr) != NULL; nptr = &rt->mfc_next)
+    for (nptr = &V_mfctable[hash]; (rt = *nptr) != NULL; nptr = &rt->mfc_next)
 	if (origin.s_addr == rt->mfc_origin.s_addr &&
 		mcastgrp.s_addr == rt->mfc_mcastgrp.s_addr &&
 		rt->mfc_stall == NULL)
@@ -1294,11 +1362,12 @@
     struct ip_moptions *imo)
 {
     INIT_VNET_INET(curvnet);
+    INIT_VNET_MROUTE(curvnet);
     struct mfc *rt;
     int error;
     vifi_t vifi;
 
-    if (mrtdebug & DEBUG_FORWARD)
+    if (V_mrtdebug & DEBUG_FORWARD)
 	log(LOG_DEBUG, "ip_mforward: src %lx, dst %lx, ifp %p\n",
 	    (u_long)ntohl(ip->ip_src.s_addr), (u_long)ntohl(ip->ip_dst.s_addr),
 	    (void *)ifp);
@@ -1326,11 +1395,11 @@
 
     VIF_LOCK();
     MFC_LOCK();
-    if (imo && ((vifi = imo->imo_multicast_vif) < numvifs)) {
+    if (imo && ((vifi = imo->imo_multicast_vif) < V_numvifs)) {
 	if (ip->ip_ttl < MAXTTL)
 	    ip->ip_ttl++;	/* compensate for -1 in *_send routines */
-	if (rsvpdebug && ip->ip_p == IPPROTO_RSVP) {
-	    struct vif *vifp = viftable + vifi;
+	if (V_rsvpdebug && ip->ip_p == IPPROTO_RSVP) {
+	    struct vif *vifp = V_viftable + vifi;
 
 	    printf("Sending IPPROTO_RSVP from %lx to %lx on vif %d (%s%s)\n",
 		(long)ntohl(ip->ip_src.s_addr), (long)ntohl(ip->ip_dst.s_addr),
@@ -1343,7 +1412,7 @@
 	VIF_UNLOCK();
 	return error;
     }
-    if (rsvpdebug && ip->ip_p == IPPROTO_RSVP) {
+    if (V_rsvpdebug && ip->ip_p == IPPROTO_RSVP) {
 	printf("Warning: IPPROTO_RSVP from %lx to %lx without vif option\n",
 	    (long)ntohl(ip->ip_src.s_addr), (long)ntohl(ip->ip_dst.s_addr));
 	if (!imo)
@@ -1363,7 +1432,7 @@
     /*
      * Determine forwarding vifs from the forwarding cache table
      */
-    ++mrtstat.mrts_mfc_lookups;
+    ++V_mrtstat.mrts_mfc_lookups;
     rt = mfc_find(ip->ip_src.s_addr, ip->ip_dst.s_addr);
 
     /* Entry exists, so forward if necessary */
@@ -1383,10 +1452,10 @@
 	u_long hash;
 	int hlen = ip->ip_hl << 2;
 
-	++mrtstat.mrts_mfc_misses;
+	++V_mrtstat.mrts_mfc_misses;
 
-	mrtstat.mrts_no_route++;
-	if (mrtdebug & (DEBUG_FORWARD | DEBUG_MFC))
+	V_mrtstat.mrts_no_route++;
+	if (V_mrtdebug & (DEBUG_FORWARD | DEBUG_MFC))
 	    log(LOG_DEBUG, "ip_mforward: no rte s %lx g %lx\n",
 		(u_long)ntohl(ip->ip_src.s_addr),
 		(u_long)ntohl(ip->ip_dst.s_addr));
@@ -1414,7 +1483,7 @@
 
 	/* is there an upcall waiting for this flow ? */
 	hash = MFCHASH(ip->ip_src.s_addr, ip->ip_dst.s_addr);
-	for (rt = mfctable[hash]; rt; rt = rt->mfc_next) {
+	for (rt = V_mfctable[hash]; rt; rt = rt->mfc_next) {
 	    if ((ip->ip_src.s_addr == rt->mfc_origin.s_addr) &&
 		    (ip->ip_dst.s_addr == rt->mfc_mcastgrp.s_addr) &&
 		    (rt->mfc_stall != NULL))
@@ -1431,9 +1500,9 @@
 	     * Locate the vifi for the incoming interface for this packet.
 	     * If none found, drop packet.
 	     */
-	    for (vifi=0; vifi < numvifs && viftable[vifi].v_ifp != ifp; vifi++)
+	    for (vifi=0; vifi < V_numvifs && V_viftable[vifi].v_ifp != ifp; vifi++)
 		;
-	    if (vifi >= numvifs)	/* vif not found, drop packet */
+	    if (vifi >= V_numvifs)	/* vif not found, drop packet */
 		goto non_fatal;
 
 	    /* no upcall, so make a new entry */
@@ -1455,12 +1524,12 @@
 	    im->im_mbz = 0;
 	    im->im_vif = vifi;
 
-	    mrtstat.mrts_upcalls++;
+	    V_mrtstat.mrts_upcalls++;
 
 	    k_igmpsrc.sin_addr = ip->ip_src;
 	    if (socket_send(V_ip_mrouter, mm, &k_igmpsrc) < 0) {
 		log(LOG_WARNING, "ip_mforward: ip_mrouter socket queue full\n");
-		++mrtstat.mrts_upq_sockfull;
+		++V_mrtstat.mrts_upq_sockfull;
 fail1:
 		free(rt, M_MRTABLE);
 fail:
@@ -1475,8 +1544,8 @@
 	    rt->mfc_origin.s_addr     = ip->ip_src.s_addr;
 	    rt->mfc_mcastgrp.s_addr   = ip->ip_dst.s_addr;
 	    rt->mfc_expire	      = UPCALL_EXPIRE;
-	    nexpire[hash]++;
-	    for (i = 0; i < numvifs; i++) {
+	    V_nexpire[hash]++;
+	    for (i = 0; i < V_numvifs; i++) {
 		rt->mfc_ttls[i] = 0;
 		rt->mfc_flags[i] = 0;
 	    }
@@ -1487,8 +1556,8 @@
 	    rt->mfc_bw_meter = NULL;
 
 	    /* link into table */
-	    rt->mfc_next   = mfctable[hash];
-	    mfctable[hash] = rt;
+	    rt->mfc_next   = V_mfctable[hash];
+	    V_mfctable[hash] = rt;
 	    rt->mfc_stall = rte;
 
 	} else {
@@ -1505,7 +1574,7 @@
 		npkts++;
 
 	    if (npkts > MAX_UPQ) {
-		mrtstat.mrts_upq_ovflw++;
+		V_mrtstat.mrts_upq_ovflw++;
 non_fatal:
 		free(rte, M_MRTABLE);
 		m_freem(mb0);
@@ -1535,15 +1604,16 @@
 static void
 expire_upcalls(void *unused)
 {
+    INIT_VNET_MROUTE( ((struct vnet *)unused) );
     struct rtdetq *rte;
     struct mfc *mfc, **nptr;
     int i;
 
     MFC_LOCK();
     for (i = 0; i < MFCTBLSIZ; i++) {
-	if (nexpire[i] == 0)
+	if (V_nexpire[i] == 0)
 	    continue;
-	nptr = &mfctable[i];
+	nptr = &V_mfctable[i];
 	for (mfc = *nptr; mfc != NULL; mfc = *nptr) {
 	    /*
 	     * Skip real cache entries
@@ -1552,7 +1622,7 @@
 	     */
 	    if (mfc->mfc_stall != NULL && mfc->mfc_expire != 0 &&
 		    --mfc->mfc_expire == 0) {
-		if (mrtdebug & DEBUG_EXPIRE)
+		if (V_mrtdebug & DEBUG_EXPIRE)
 		    log(LOG_DEBUG, "expire_upcalls: expiring (%lx %lx)\n",
 			(u_long)ntohl(mfc->mfc_origin.s_addr),
 			(u_long)ntohl(mfc->mfc_mcastgrp.s_addr));
@@ -1567,8 +1637,8 @@
 		    free(rte, M_MRTABLE);
 		    rte = n;
 		}
-		++mrtstat.mrts_cache_cleanups;
-		nexpire[i]--;
+		++V_mrtstat.mrts_cache_cleanups;
+		V_nexpire[i]--;
 
 		/*
 		 * free the bw_meter entries
@@ -1587,9 +1657,8 @@
 	    }
 	}
     }
+    callout_reset(&V_expire_upcalls_ch, EXPIRE_TIMEOUT, expire_upcalls, unused);
     MFC_UNLOCK();
-
-    callout_reset(&expire_upcalls_ch, EXPIRE_TIMEOUT, expire_upcalls, NULL);
 }
 
 /*
@@ -1599,6 +1668,7 @@
 ip_mdq(struct mbuf *m, struct ifnet *ifp, struct mfc *rt, vifi_t xmt_vif)
 {
     INIT_VNET_INET(curvnet);
+    INIT_VNET_MROUTE(curvnet);
     struct ip  *ip = mtod(m, struct ip *);
     vifi_t vifi;
     int plen = ip->ip_len;
@@ -1610,11 +1680,11 @@
      *
      * (since vifi_t is u_short, -1 becomes MAXUSHORT, which > numvifs.)
      */
-    if (xmt_vif < numvifs) {
-	if (viftable[xmt_vif].v_flags & VIFF_REGISTER)
-		pim_register_send(ip, viftable + xmt_vif, m, rt);
+    if (xmt_vif < V_numvifs) {
+	if (V_viftable[xmt_vif].v_flags & VIFF_REGISTER)
+		pim_register_send(ip, V_viftable + xmt_vif, m, rt);
 	else
-		phyint_send(ip, viftable + xmt_vif, m);
+		phyint_send(ip, V_viftable + xmt_vif, m);
 	return 1;
     }
 
@@ -1622,12 +1692,12 @@
      * Don't forward if it didn't arrive from the parent vif for its origin.
      */
     vifi = rt->mfc_parent;
-    if ((vifi >= numvifs) || (viftable[vifi].v_ifp != ifp)) {
+    if ((vifi >= V_numvifs) || (V_viftable[vifi].v_ifp != ifp)) {
 	/* came in the wrong interface */
-	if (mrtdebug & DEBUG_FORWARD)
+	if (V_mrtdebug & DEBUG_FORWARD)
 	    log(LOG_DEBUG, "wrong if: ifp %p vifi %d vififp %p\n",
-		(void *)ifp, vifi, (void *)viftable[vifi].v_ifp);
-	++mrtstat.mrts_wrong_if;
+		(void *)ifp, vifi, (void *)V_viftable[vifi].v_ifp);
+	++V_mrtstat.mrts_wrong_if;
 	++rt->mfc_wrong_if;
 	/*
 	 * If we are doing PIM assert processing, send a message
@@ -1637,17 +1707,18 @@
 	 * can complete the SPT switch, regardless of the type
 	 * of the iif (broadcast media, GRE tunnel, etc).
 	 */
-	if (pim_assert && (vifi < numvifs) && viftable[vifi].v_ifp) {
+	if (V_pim_assert && (vifi < V_numvifs) && V_viftable[vifi].v_ifp) {
 	    struct timeval now;
 	    u_long delta;
 
-	    if (ifp == &multicast_register_if)
-		pimstat.pims_rcv_registers_wrongiif++;
+	    if (ifp == &V_multicast_register_if)
+		V_pimstat.pims_rcv_registers_wrongiif++;
 
 	    /* Get vifi for the incoming packet */
-	    for (vifi=0; vifi < numvifs && viftable[vifi].v_ifp != ifp; vifi++)
+	    for (vifi=0; vifi < V_numvifs && V_viftable[vifi].v_ifp != ifp;
+		vifi++)
 		;
-	    if (vifi >= numvifs)
+	    if (vifi >= V_numvifs)
 		return 0;	/* The iif is not found: ignore the packet. */
 
 	    if (rt->mfc_flags[vifi] & MRT_MFC_FLAGS_DISABLE_WRONGVIF)
@@ -1675,13 +1746,13 @@
 		im->im_mbz		= 0;
 		im->im_vif		= vifi;
 
-		mrtstat.mrts_upcalls++;
+		V_mrtstat.mrts_upcalls++;
 
 		k_igmpsrc.sin_addr = im->im_src;
 		if (socket_send(V_ip_mrouter, mm, &k_igmpsrc) < 0) {
 		    log(LOG_WARNING,
 			"ip_mforward: ip_mrouter socket queue full\n");
-		    ++mrtstat.mrts_upq_sockfull;
+		    ++V_mrtstat.mrts_upq_sockfull;
 		    return ENOBUFS;
 		}
 	    }
@@ -1690,12 +1761,12 @@
     }
 
     /* If I sourced this packet, it counts as output, else it was input. */
-    if (ip->ip_src.s_addr == viftable[vifi].v_lcl_addr.s_addr) {
-	viftable[vifi].v_pkt_out++;
-	viftable[vifi].v_bytes_out += plen;
+    if (ip->ip_src.s_addr == V_viftable[vifi].v_lcl_addr.s_addr) {
+	V_viftable[vifi].v_pkt_out++;
+	V_viftable[vifi].v_bytes_out += plen;
     } else {
-	viftable[vifi].v_pkt_in++;
-	viftable[vifi].v_bytes_in += plen;
+	V_viftable[vifi].v_pkt_in++;
+	V_viftable[vifi].v_bytes_in += plen;
     }
     rt->mfc_pkt_cnt++;
     rt->mfc_byte_cnt += plen;
@@ -1706,14 +1777,14 @@
      *		- the ttl exceeds the vif's threshold
      *		- there are group members downstream on interface
      */
-    for (vifi = 0; vifi < numvifs; vifi++)
+    for (vifi = 0; vifi < V_numvifs; vifi++)
 	if ((rt->mfc_ttls[vifi] > 0) && (ip->ip_ttl > rt->mfc_ttls[vifi])) {
-	    viftable[vifi].v_pkt_out++;
-	    viftable[vifi].v_bytes_out += plen;
-	    if (viftable[vifi].v_flags & VIFF_REGISTER)
-		pim_register_send(ip, viftable + vifi, m, rt);
+	    V_viftable[vifi].v_pkt_out++;
+	    V_viftable[vifi].v_bytes_out += plen;
+	    if (V_viftable[vifi].v_flags & VIFF_REGISTER)
+		pim_register_send(ip, V_viftable + vifi, m, rt);
 	    else
-		phyint_send(ip, viftable + vifi, m);
+		phyint_send(ip, V_viftable + vifi, m);
 	}
 
     /*
@@ -1738,8 +1809,9 @@
 static int
 X_legal_vif_num(int vif)
 {
+    INIT_VNET_MROUTE(curvnet);
     /* XXX unlocked, matter? */
-    return (vif >= 0 && vif < numvifs);
+    return (vif >= 0 && vif < V_numvifs);
 }
 
 /*
@@ -1748,9 +1820,10 @@
 static u_long
 X_ip_mcast_src(int vifi)
 {
+    INIT_VNET_MROUTE(curvnet);
     /* XXX unlocked, matter? */
-    if (vifi >= 0 && vifi < numvifs)
-	return viftable[vifi].v_lcl_addr.s_addr;
+    if (vifi >= 0 && vifi < V_numvifs)
+	return V_viftable[vifi].v_lcl_addr.s_addr;
     else
 	return INADDR_ANY;
 }
@@ -1780,6 +1853,7 @@
 static void
 send_packet(struct vif *vifp, struct mbuf *m)
 {
+	INIT_VNET_MROUTE(curvnet);
 	struct ip_moptions imo;
 	struct in_multi *imm[2];
 	int error;
@@ -1801,16 +1875,17 @@
 	 * the loopback interface, thus preventing looping.
 	 */
 	error = ip_output(m, NULL, &vifp->v_route, IP_FORWARDING, &imo, NULL);
-	if (mrtdebug & DEBUG_XMIT) {
+	if (V_mrtdebug & DEBUG_XMIT) {
 	    log(LOG_DEBUG, "phyint_send on vif %td err %d\n",
-		vifp - viftable, error);
+		vifp - V_viftable, error);
 	}
 }
 
 static int
 X_ip_rsvp_vif(struct socket *so, struct sockopt *sopt)
 {
-    INIT_VNET_INET(curvnet);
+    INIT_VNET_INET(so->so_vnet);
+    INIT_VNET_MROUTE(so->so_vnet);
     int error, vifi;
 
     if (so->so_type != SOCK_RAW || so->so_proto->pr_protocol != IPPROTO_RSVP)
@@ -1822,39 +1897,39 @@
 
     VIF_LOCK();
 
-    if (vifi < 0 || vifi >= numvifs) {	/* Error if vif is invalid */
+    if (vifi < 0 || vifi >= V_numvifs) {	/* Error if vif is invalid */
 	VIF_UNLOCK();
 	return EADDRNOTAVAIL;
     }
 
     if (sopt->sopt_name == IP_RSVP_VIF_ON) {
 	/* Check if socket is available. */
-	if (viftable[vifi].v_rsvpd != NULL) {
+	if (V_viftable[vifi].v_rsvpd != NULL) {
 	    VIF_UNLOCK();
 	    return EADDRINUSE;
 	}
 
-	viftable[vifi].v_rsvpd = so;
+	V_viftable[vifi].v_rsvpd = so;
 	/* This may seem silly, but we need to be sure we don't over-increment
 	 * the RSVP counter, in case something slips up.
 	 */
-	if (!viftable[vifi].v_rsvp_on) {
-	    viftable[vifi].v_rsvp_on = 1;
+	if (!V_viftable[vifi].v_rsvp_on) {
+	    V_viftable[vifi].v_rsvp_on = 1;
 	    V_rsvp_on++;
 	}
     } else { /* must be VIF_OFF */
 	/*
 	 * XXX as an additional consistency check, one could make sure
-	 * that viftable[vifi].v_rsvpd == so, otherwise passing so as
+	 * that V_viftable[vifi].v_rsvpd == so, otherwise passing so as
 	 * first parameter is pretty useless.
 	 */
-	viftable[vifi].v_rsvpd = NULL;
+	V_viftable[vifi].v_rsvpd = NULL;
 	/*
 	 * This may seem silly, but we need to be sure we don't over-decrement
 	 * the RSVP counter, in case something slips up.
 	 */
-	if (viftable[vifi].v_rsvp_on) {
-	    viftable[vifi].v_rsvp_on = 0;
+	if (V_viftable[vifi].v_rsvp_on) {
+	    V_viftable[vifi].v_rsvp_on = 0;
 	    V_rsvp_on--;
 	}
     }
@@ -1865,7 +1940,8 @@
 static void
 X_ip_rsvp_force_done(struct socket *so)
 {
-    INIT_VNET_INET(curvnet);
+    INIT_VNET_INET(so->so_vnet);
+    INIT_VNET_MROUTE(so->so_vnet);
     int vifi;
 
     /* Don't bother if it is not the right type of socket. */
@@ -1877,14 +1953,14 @@
     /* The socket may be attached to more than one vif...this
      * is perfectly legal.
      */
-    for (vifi = 0; vifi < numvifs; vifi++) {
-	if (viftable[vifi].v_rsvpd == so) {
-	    viftable[vifi].v_rsvpd = NULL;
+    for (vifi = 0; vifi < V_numvifs; vifi++) {
+	if (V_viftable[vifi].v_rsvpd == so) {
+	    V_viftable[vifi].v_rsvpd = NULL;
 	    /* This may seem silly, but we need to be sure we don't
 	     * over-decrement the RSVP counter, in case something slips up.
 	     */
-	    if (viftable[vifi].v_rsvp_on) {
-		viftable[vifi].v_rsvp_on = 0;
+	    if (V_viftable[vifi].v_rsvp_on) {
+		V_viftable[vifi].v_rsvp_on = 0;
 		V_rsvp_on--;
 	    }
 	}
@@ -1897,12 +1973,13 @@
 X_rsvp_input(struct mbuf *m, int off)
 {
     INIT_VNET_INET(curvnet);
+    INIT_VNET_MROUTE(curvnet);
     int vifi;
     struct ip *ip = mtod(m, struct ip *);
     struct sockaddr_in rsvp_src = { sizeof rsvp_src, AF_INET };
     struct ifnet *ifp;
 
-    if (rsvpdebug)
+    if (V_rsvpdebug)
 	printf("rsvp_input: rsvp_on %d\n", V_rsvp_on);
 
     /* Can still get packets with rsvp_on = 0 if there is a local member
@@ -1914,7 +1991,7 @@
 	return;
     }
 
-    if (rsvpdebug)
+    if (V_rsvpdebug)
 	printf("rsvp_input: check vifs\n");
 
 #ifdef DIAGNOSTIC
@@ -1925,14 +2002,14 @@
 
     VIF_LOCK();
     /* Find which vif the packet arrived on. */
-    for (vifi = 0; vifi < numvifs; vifi++)
-	if (viftable[vifi].v_ifp == ifp)
+    for (vifi = 0; vifi < V_numvifs; vifi++)
+	if (V_viftable[vifi].v_ifp == ifp)
 	    break;
 
-    if (vifi == numvifs || viftable[vifi].v_rsvpd == NULL) {
+    if (vifi == V_numvifs || V_viftable[vifi].v_rsvpd == NULL) {
 	/*
 	 * Drop the lock here to avoid holding it across rip_input.
-	 * This could make rsvpdebug printfs wrong.  If you care,
+	 * This could make V_rsvpdebug printfs wrong.  If you care,
 	 * record the state of stuff before dropping the lock.
 	 */
 	VIF_UNLOCK();
@@ -1942,13 +2019,13 @@
 	 * is no specific socket for this vif.
 	 */
 	if (V_ip_rsvpd != NULL) {
-	    if (rsvpdebug)
+	    if (V_rsvpdebug)
 		printf("rsvp_input: Sending packet up old-style socket\n");
 	    rip_input(m, off);  /* xxx */
 	} else {
-	    if (rsvpdebug && vifi == numvifs)
+	    if (V_rsvpdebug && vifi == V_numvifs)
 		printf("rsvp_input: Can't find vif for packet.\n");
-	    else if (rsvpdebug && viftable[vifi].v_rsvpd == NULL)
+	    else if (V_rsvpdebug && V_viftable[vifi].v_rsvpd == NULL)
 		printf("rsvp_input: No socket defined for vif %d\n",vifi);
 	    m_freem(m);
 	}
@@ -1956,15 +2033,15 @@
     }
     rsvp_src.sin_addr = ip->ip_src;
 
-    if (rsvpdebug && m)
+    if (V_rsvpdebug && m)
 	printf("rsvp_input: m->m_len = %d, sbspace() = %ld\n",
-	       m->m_len,sbspace(&(viftable[vifi].v_rsvpd->so_rcv)));
+	       m->m_len,sbspace(&(V_viftable[vifi].v_rsvpd->so_rcv)));
 
-    if (socket_send(viftable[vifi].v_rsvpd, m, &rsvp_src) < 0) {
-	if (rsvpdebug)
+    if (socket_send(V_viftable[vifi].v_rsvpd, m, &rsvp_src) < 0) {
+	if (V_rsvpdebug)
 	    printf("rsvp_input: Failed to append to socket\n");
     } else {
-	if (rsvpdebug)
+	if (V_rsvpdebug)
 	    printf("rsvp_input: send packet up\n");
     }
     VIF_UNLOCK();
@@ -2004,6 +2081,7 @@
 static int
 add_bw_upcall(struct bw_upcall *req)
 {
+    INIT_VNET_MROUTE(curvnet);
     struct mfc *mfc;
     struct timeval delta = { BW_UPCALL_THRESHOLD_INTERVAL_MIN_SEC,
 		BW_UPCALL_THRESHOLD_INTERVAL_MIN_USEC };
@@ -2011,7 +2089,7 @@
     struct bw_meter *x;
     uint32_t flags;
 
-    if (!(mrt_api_config & MRT_MFC_BW_UPCALL))
+    if (!(V_mrt_api_config & MRT_MFC_BW_UPCALL))
 	return EOPNOTSUPP;
 
     /* Test if the flags are valid */
@@ -2096,10 +2174,11 @@
 static int
 del_bw_upcall(struct bw_upcall *req)
 {
+    INIT_VNET_MROUTE(curvnet);
     struct mfc *mfc;
     struct bw_meter *x;
 
-    if (!(mrt_api_config & MRT_MFC_BW_UPCALL))
+    if (!(V_mrt_api_config & MRT_MFC_BW_UPCALL))
 	return EOPNOTSUPP;
 
     MFC_LOCK();
@@ -2252,6 +2331,7 @@
 static void
 bw_meter_prepare_upcall(struct bw_meter *x, struct timeval *nowp)
 {
+    INIT_VNET_MROUTE(curvnet);
     struct timeval delta;
     struct bw_upcall *u;
 
@@ -2266,13 +2346,13 @@
     /*
      * If there are too many pending upcalls, deliver them now
      */
-    if (bw_upcalls_n >= BW_UPCALLS_MAX)
+    if (V_bw_upcalls_n >= BW_UPCALLS_MAX)
 	bw_upcalls_send();
 
     /*
      * Set the bw_upcall entry
      */
-    u = &bw_upcalls[bw_upcalls_n++];
+    u = &V_bw_upcalls[V_bw_upcalls_n++];
     u->bu_src = x->bm_mfc->mfc_origin;
     u->bu_dst = x->bm_mfc->mfc_mcastgrp;
     u->bu_threshold.b_time = x->bm_threshold.b_time;
@@ -2299,8 +2379,9 @@
 bw_upcalls_send(void)
 {
     INIT_VNET_INET(curvnet);
+    INIT_VNET_MROUTE(curvnet);
     struct mbuf *m;
-    int len = bw_upcalls_n * sizeof(bw_upcalls[0]);
+    int len = V_bw_upcalls_n * sizeof(V_bw_upcalls[0]);
     struct sockaddr_in k_igmpsrc = { sizeof k_igmpsrc, AF_INET };
     static struct igmpmsg igmpmsg = { 0,		/* unused1 */
 				      0,		/* unused2 */
@@ -2313,10 +2394,10 @@
 
     MFC_LOCK_ASSERT();
 
-    if (bw_upcalls_n == 0)
+    if (V_bw_upcalls_n == 0)
 	return;			/* No pending upcalls */
 
-    bw_upcalls_n = 0;
+    V_bw_upcalls_n = 0;
 
     /*
      * Allocate a new mbuf, initialize it with the header and
@@ -2330,16 +2411,16 @@
 
     m->m_len = m->m_pkthdr.len = 0;
     m_copyback(m, 0, sizeof(struct igmpmsg), (caddr_t)&igmpmsg);
-    m_copyback(m, sizeof(struct igmpmsg), len, (caddr_t)&bw_upcalls[0]);
+    m_copyback(m, sizeof(struct igmpmsg), len, (caddr_t)&V_bw_upcalls[0]);
 
     /*
      * Send the upcalls
      * XXX do we need to set the address in k_igmpsrc ?
      */
-    mrtstat.mrts_upcalls++;
+    V_mrtstat.mrts_upcalls++;
     if (socket_send(V_ip_mrouter, m, &k_igmpsrc) < 0) {
 	log(LOG_WARNING, "bw_upcalls_send: ip_mrouter socket queue full\n");
-	++mrtstat.mrts_upq_sockfull;
+	++V_mrtstat.mrts_upq_sockfull;
     }
 }
 
@@ -2364,6 +2445,7 @@
 static void
 schedule_bw_meter(struct bw_meter *x, struct timeval *nowp)
 {
+    INIT_VNET_MROUTE(curvnet);
     int time_hash;
 
     MFC_LOCK_ASSERT();
@@ -2383,8 +2465,8 @@
      * Compute the timeout hash value and insert the entry
      */
     BW_METER_TIMEHASH(x, time_hash);
-    x->bm_time_next = bw_meter_timers[time_hash];
-    bw_meter_timers[time_hash] = x;
+    x->bm_time_next = V_bw_meter_timers[time_hash];
+    V_bw_meter_timers[time_hash] = x;
     x->bm_time_hash = time_hash;
 }
 
@@ -2395,6 +2477,7 @@
 static void
 unschedule_bw_meter(struct bw_meter *x)
 {
+    INIT_VNET_MROUTE(curvnet);
     int time_hash;
     struct bw_meter *prev, *tmp;
 
@@ -2410,7 +2493,7 @@
     if (time_hash >= BW_METER_BUCKETS)
 	return;		/* Entry was not scheduled */
 
-    for (prev = NULL, tmp = bw_meter_timers[time_hash];
+    for (prev = NULL, tmp = V_bw_meter_timers[time_hash];
 	     tmp != NULL; prev = tmp, tmp = tmp->bm_time_next)
 	if (tmp == x)
 	    break;
@@ -2421,7 +2504,7 @@
     if (prev != NULL)
 	prev->bm_time_next = x->bm_time_next;
     else
-	bw_meter_timers[time_hash] = x->bm_time_next;
+	V_bw_meter_timers[time_hash] = x->bm_time_next;
 
     x->bm_time_next = NULL;
     x->bm_time_hash = BW_METER_BUCKETS;
@@ -2438,8 +2521,9 @@
  * looking at.
  */
 static void
-bw_meter_process()
+bw_meter_process(struct vnet *vnet)
 {
+    INIT_VNET_MROUTE(vnet);
     static uint32_t last_tv_sec;	/* last time we processed this */
 
     uint32_t loops;
@@ -2456,6 +2540,7 @@
 	loops = BW_METER_BUCKETS;
 
     MFC_LOCK();
+    CURVNET_SET(vnet);
     /*
      * Process all bins of bw_meter entries from the one after the last
      * processed to the current one. On entry, i points to the last bucket
@@ -2468,8 +2553,8 @@
 	    i = 0;
 
 	/* Disconnect the list of bw_meter entries from the bin */
-	tmp_list = bw_meter_timers[i];
-	bw_meter_timers[i] = NULL;
+	tmp_list = V_bw_meter_timers[i];
+	V_bw_meter_timers[i] = NULL;
 
 	/* Process the list of bw_meter entries */
 	while (tmp_list != NULL) {
@@ -2492,8 +2577,8 @@
 		    if (++time_hash >= BW_METER_BUCKETS)
 			time_hash = 0;
 		}
-		x->bm_time_next = bw_meter_timers[time_hash];
-		bw_meter_timers[time_hash] = x;
+		x->bm_time_next = V_bw_meter_timers[time_hash];
+		V_bw_meter_timers[time_hash] = x;
 		x->bm_time_hash = time_hash;
 
 		continue;
@@ -2520,6 +2605,7 @@
     /* Send all upcalls that are pending delivery */
     bw_upcalls_send();
 
+    CURVNET_RESTORE();
     MFC_UNLOCK();
 }
 
@@ -2529,12 +2615,14 @@
 static void
 expire_bw_upcalls_send(void *unused)
 {
+    INIT_VNET_MROUTE( (struct vnet *)unused );
     MFC_LOCK();
+    CURVNET_SET( (struct vnet*)unused );
     bw_upcalls_send();
+    callout_reset(&V_bw_upcalls_ch, BW_UPCALLS_PERIOD,
+	expire_bw_upcalls_send, unused);
+    CURVNET_RESTORE();
     MFC_UNLOCK();
-
-    callout_reset(&bw_upcalls_ch, BW_UPCALLS_PERIOD,
-	expire_bw_upcalls_send, NULL);
 }
 
 /*
@@ -2544,10 +2632,12 @@
 static void
 expire_bw_meter_process(void *unused)
 {
-    if (mrt_api_config & MRT_MFC_BW_UPCALL)
-	bw_meter_process();
+    INIT_VNET_MROUTE( (struct vnet *)unused );
+    if (V_mrt_api_config & MRT_MFC_BW_UPCALL)
+	bw_meter_process( (struct vnet *)unused );
 
-    callout_reset(&bw_meter_ch, BW_METER_PERIOD, expire_bw_meter_process, NULL);
+    callout_reset(&V_bw_meter_ch, BW_METER_PERIOD,
+	expire_bw_meter_process, unused);
 }
 
 /*
@@ -2562,16 +2652,17 @@
 pim_register_send(struct ip *ip, struct vif *vifp, struct mbuf *m,
     struct mfc *rt)
 {
+    INIT_VNET_MROUTE(curvnet);
     struct mbuf *mb_copy, *mm;
 
-    if (mrtdebug & DEBUG_PIM)
+    if (V_mrtdebug & DEBUG_PIM)
 	log(LOG_DEBUG, "pim_register_send: ");
 
     /*
      * Do not send IGMP_WHOLEPKT notifications to userland, if the
      * rendezvous point was unspecified, and we were told not to.
      */
-    if (pim_squelch_wholepkt != 0 && (mrt_api_config & MRT_MFC_RP) &&
+    if (pim_squelch_wholepkt != 0 && (V_mrt_api_config & MRT_MFC_RP) &&
 	(rt->mfc_rp.s_addr == INADDR_ANY))
 	return 0;
 
@@ -2589,7 +2680,7 @@
 	mm = m_pullup(mm, sizeof(struct ip));
 	if (mm != NULL) {
 	    ip = mtod(mm, struct ip *);
-	    if ((mrt_api_config & MRT_MFC_RP) &&
+	    if ((V_mrt_api_config & MRT_MFC_RP) &&
 		(rt->mfc_rp.s_addr != INADDR_ANY)) {
 		pim_register_send_rp(ip, vifp, mm, rt);
 	    } else {
@@ -2660,6 +2751,7 @@
     struct mbuf *mb_copy, struct mfc *rt)
 {
     INIT_VNET_INET(curvnet);
+    INIT_VNET_MROUTE(curvnet);
     struct mbuf *mb_first;
     int len = ntohs(ip->ip_len);
     struct igmpmsg *im;
@@ -2684,25 +2776,25 @@
     im = mtod(mb_first, struct igmpmsg *);
     im->im_msgtype	= IGMPMSG_WHOLEPKT;
     im->im_mbz		= 0;
-    im->im_vif		= vifp - viftable;
+    im->im_vif		= vifp - V_viftable;
     im->im_src		= ip->ip_src;
     im->im_dst		= ip->ip_dst;
 
     k_igmpsrc.sin_addr	= ip->ip_src;
 
-    mrtstat.mrts_upcalls++;
+    V_mrtstat.mrts_upcalls++;
 
     if (socket_send(V_ip_mrouter, mb_first, &k_igmpsrc) < 0) {
-	if (mrtdebug & DEBUG_PIM)
+	if (V_mrtdebug & DEBUG_PIM)
 	    log(LOG_WARNING,
 		"mcast: pim_register_send_upcall: ip_mrouter socket queue full");
-	++mrtstat.mrts_upq_sockfull;
+	++V_mrtstat.mrts_upq_sockfull;
 	return ENOBUFS;
     }
 
     /* Keep statistics */
-    pimstat.pims_snd_registers_msgs++;
-    pimstat.pims_snd_registers_bytes += len;
+    V_pimstat.pims_snd_registers_msgs++;
+    V_pimstat.pims_snd_registers_bytes += len;
 
     return 0;
 }
@@ -2715,6 +2807,7 @@
     struct mfc *rt)
 {
     INIT_VNET_INET(curvnet);
+    INIT_VNET_MROUTE(curvnet);
     struct mbuf *mb_first;
     struct ip *ip_outer;
     struct pim_encap_pimhdr *pimhdr;
@@ -2723,7 +2816,7 @@
 
     VIF_LOCK_ASSERT();
 
-    if ((vifi >= numvifs) || (viftable[vifi].v_lcl_addr.s_addr == 0)) {
+    if ((vifi >= V_numvifs) || (V_viftable[vifi].v_lcl_addr.s_addr == 0)) {
 	m_freem(mb_copy);
 	return EADDRNOTAVAIL;		/* The iif vif is invalid */
     }
@@ -2749,7 +2842,7 @@
     *ip_outer = pim_encap_iphdr;
     ip_outer->ip_id = ip_newid();
     ip_outer->ip_len = len + sizeof(pim_encap_iphdr) + sizeof(pim_encap_pimhdr);
-    ip_outer->ip_src = viftable[vifi].v_lcl_addr;
+    ip_outer->ip_src = V_viftable[vifi].v_lcl_addr;
     ip_outer->ip_dst = rt->mfc_rp;
     /*
      * Copy the inner header TOS to the outer header, and take care of the
@@ -2762,7 +2855,7 @@
 					 + sizeof(pim_encap_iphdr));
     *pimhdr = pim_encap_pimhdr;
     /* If the iif crosses a border, set the Border-bit */
-    if (rt->mfc_flags[vifi] & MRT_MFC_FLAGS_BORDER_VIF & mrt_api_config)
+    if (rt->mfc_flags[vifi] & MRT_MFC_FLAGS_BORDER_VIF & V_mrt_api_config)
 	pimhdr->flags |= htonl(PIM_BORDER_REGISTER);
 
     mb_first->m_data += sizeof(pim_encap_iphdr);
@@ -2772,8 +2865,8 @@
     send_packet(vifp, mb_first);
 
     /* Keep statistics */
-    pimstat.pims_snd_registers_msgs++;
-    pimstat.pims_snd_registers_bytes += len;
+    V_pimstat.pims_snd_registers_msgs++;
+    V_pimstat.pims_snd_registers_bytes += len;
 
     return 0;
 }
@@ -2807,6 +2900,7 @@
 void
 pim_input(struct mbuf *m, int off)
 {
+    INIT_VNET_MROUTE(curvnet);
     struct ip *ip = mtod(m, struct ip *);
     struct pim *pim;
     int minlen;
@@ -2815,14 +2909,14 @@
     int iphlen = off;
 
     /* Keep statistics */
-    pimstat.pims_rcv_total_msgs++;
-    pimstat.pims_rcv_total_bytes += datalen;
+    V_pimstat.pims_rcv_total_msgs++;
+    V_pimstat.pims_rcv_total_bytes += datalen;
 
     /*
      * Validate lengths
      */
     if (datalen < PIM_MINLEN) {
-	pimstat.pims_rcv_tooshort++;
+	V_pimstat.pims_rcv_tooshort++;
 	log(LOG_ERR, "pim_input: packet size too small %d from %lx\n",
 	    datalen, (u_long)ip->ip_src.s_addr);
 	m_freem(m);
@@ -2866,8 +2960,8 @@
     if (PIM_VT_T(pim->pim_vt) == PIM_REGISTER && in_cksum(m, PIM_MINLEN) == 0) {
 	/* do nothing, checksum okay */
     } else if (in_cksum(m, datalen)) {
-	pimstat.pims_rcv_badsum++;
-	if (mrtdebug & DEBUG_PIM)
+	V_pimstat.pims_rcv_badsum++;
+	if (V_mrtdebug & DEBUG_PIM)
 	    log(LOG_DEBUG, "pim_input: invalid checksum");
 	m_freem(m);
 	return;
@@ -2875,7 +2969,7 @@
 
     /* PIM version check */
     if (PIM_VT_V(pim->pim_vt) < PIM_VERSION) {
-	pimstat.pims_rcv_badversion++;
+	V_pimstat.pims_rcv_badversion++;
 	log(LOG_ERR, "pim_input: incorrect version %d, expecting %d\n",
 	    PIM_VT_V(pim->pim_vt), PIM_VERSION);
 	m_freem(m);
@@ -2899,24 +2993,24 @@
 	struct ifnet *vifp;
 
 	VIF_LOCK();
-	if ((reg_vif_num >= numvifs) || (reg_vif_num == VIFI_INVALID)) {
+	if ((V_reg_vif_num >= V_numvifs) || (V_reg_vif_num == VIFI_INVALID)) {
 	    VIF_UNLOCK();
-	    if (mrtdebug & DEBUG_PIM)
+	    if (V_mrtdebug & DEBUG_PIM)
 		log(LOG_DEBUG,
-		    "pim_input: register vif not set: %d\n", reg_vif_num);
+		    "pim_input: register vif not set: %d\n", V_reg_vif_num);
 	    m_freem(m);
 	    return;
 	}
 	/* XXX need refcnt? */
-	vifp = viftable[reg_vif_num].v_ifp;
+	vifp = V_viftable[V_reg_vif_num].v_ifp;
 	VIF_UNLOCK();
 
 	/*
 	 * Validate length
 	 */
 	if (datalen < PIM_REG_MINLEN) {
-	    pimstat.pims_rcv_tooshort++;
-	    pimstat.pims_rcv_badregisters++;
+	    V_pimstat.pims_rcv_tooshort++;
+	    V_pimstat.pims_rcv_badregisters++;
 	    log(LOG_ERR,
 		"pim_input: register packet size too small %d from %lx\n",
 		datalen, (u_long)ip->ip_src.s_addr);
@@ -2927,7 +3021,7 @@
 	reghdr = (u_int32_t *)(pim + 1);
 	encap_ip = (struct ip *)(reghdr + 1);
 
-	if (mrtdebug & DEBUG_PIM) {
+	if (V_mrtdebug & DEBUG_PIM) {
 	    log(LOG_DEBUG,
 		"pim_input[register], encap_ip: %lx -> %lx, encap_ip len %d\n",
 		(u_long)ntohl(encap_ip->ip_src.s_addr),
@@ -2937,8 +3031,8 @@
 
 	/* verify the version number of the inner packet */
 	if (encap_ip->ip_v != IPVERSION) {
-	    pimstat.pims_rcv_badregisters++;
-	    if (mrtdebug & DEBUG_PIM) {
+	    V_pimstat.pims_rcv_badregisters++;
+	    if (V_mrtdebug & DEBUG_PIM) {
 		log(LOG_DEBUG, "pim_input: invalid IP version (%d) "
 		    "of the inner packet\n", encap_ip->ip_v);
 	    }
@@ -2948,8 +3042,8 @@
 
 	/* verify the inner packet is destined to a mcast group */
 	if (!IN_MULTICAST(ntohl(encap_ip->ip_dst.s_addr))) {
-	    pimstat.pims_rcv_badregisters++;
-	    if (mrtdebug & DEBUG_PIM)
+	    V_pimstat.pims_rcv_badregisters++;
+	    if (V_mrtdebug & DEBUG_PIM)
 		log(LOG_DEBUG,
 		    "pim_input: inner packet of register is not "
 		    "multicast %lx\n",
@@ -3000,21 +3094,21 @@
 
 	/* Keep statistics */
 	/* XXX: registers_bytes include only the encap. mcast pkt */
-	pimstat.pims_rcv_registers_msgs++;
-	pimstat.pims_rcv_registers_bytes += ntohs(encap_ip->ip_len);
+	V_pimstat.pims_rcv_registers_msgs++;
+	V_pimstat.pims_rcv_registers_bytes += ntohs(encap_ip->ip_len);
 
 	/*
 	 * forward the inner ip packet; point m_data at the inner ip.
 	 */
 	m_adj(m, iphlen + PIM_MINLEN);
 
-	if (mrtdebug & DEBUG_PIM) {
+	if (V_mrtdebug & DEBUG_PIM) {
 	    log(LOG_DEBUG,
 		"pim_input: forwarding decapsulated register: "
 		"src %lx, dst %lx, vif %d\n",
 		(u_long)ntohl(encap_ip->ip_src.s_addr),
 		(u_long)ntohl(encap_ip->ip_dst.s_addr),
-		reg_vif_num);
+		V_reg_vif_num);
 	}
 	/* NB: vifp was collected above; can it change on us? */
 	if_simloop(vifp, m, dst.sin_family, 0);
@@ -3037,6 +3131,41 @@
     return;
 }
 
+#ifdef VIMAGE
+/* initialization for multicast routing state */
+static int
+vnet_mroute_iattach(unused)
+    const void *unused;
+{
+    INIT_VNET_MROUTE(curvnet);
+
+    V_reg_vif_num = VIFI_INVALID;
+    MROUTER_LOCK_INIT();
+    MFC_LOCK_INIT();
+    VIF_LOCK_INIT();
+    ip_mrouter_reset();
+    return 0;
+}
+
+/* de-initialization for multicast routing state */
+static int
+vnet_mroute_idetach(unused)
+    const void *unused;
+{
+    INIT_VNET_MROUTE(curvnet);
+
+    X_ip_mrouter_done();
+#ifdef INET6
+    X_ip6_mrouter_done();
+#endif
+
+    VIF_LOCK_DESTROY();
+    MFC_LOCK_DESTROY();
+    MROUTER_LOCK_DESTROY();
+    return 0;
+}
+#endif /* VIMAGE */
+
 /*
  * XXX: This is common code for dealing with initialization for both
  * the IPv4 and IPv6 multicast forwarding paths. It could do with cleanup.
@@ -3045,12 +3174,15 @@
 ip_mroute_modevent(module_t mod, int type, void *unused)
 {
     INIT_VNET_INET(curvnet);
+    INIT_VNET_INET6(curvnet);
+    INIT_VNET_MROUTE(curvnet);
     switch (type) {
     case MOD_LOAD:
-	MROUTER_LOCK_INIT();
-	MFC_LOCK_INIT();
-	VIF_LOCK_INIT();
-	ip_mrouter_reset();
+#ifdef VIMAGE
+	vnet_mod_register(&vnet_mroute_modinfo);
+#else
+	vnet_mroute_iattach(NULL);
+#endif
 	TUNABLE_ULONG_FETCH("net.inet.pim.squelch_wholepkt",
 	    &pim_squelch_wholepkt);
 
@@ -3113,17 +3245,21 @@
 	 */
 	if (V_ip_mrouter
 #ifdef INET6
-	    || ip6_mrouter
+	    || V_ip6_mrouter
 #endif
 	)
 	    return EINVAL;
 
+#ifdef VIMAGE
+	vnet_mod_deregister(&vnet_mroute_modinfo);
+#else
+	vnet_mroute_idetach(NULL)
+#endif
 #ifdef INET6
 	if (pim6_encap_cookie) {
 	    encap_detach(pim6_encap_cookie);
 	    pim6_encap_cookie = NULL;
 	}
-	X_ip6_mrouter_done();
 	ip6_mforward = NULL;
 	ip6_mrouter_done = NULL;
 	ip6_mrouter_get = NULL;
@@ -3135,7 +3271,6 @@
 	    encap_detach(pim_encap_cookie);
 	    pim_encap_cookie = NULL;
 	}
-	X_ip_mrouter_done();
 	ip_mcast_src = NULL;
 	ip_mforward = NULL;
 	ip_mrouter_done = NULL;
@@ -3148,10 +3283,6 @@
 	legal_vif_num = NULL;
 	mrt_ioctl = NULL;
 	rsvp_input_p = NULL;
-
-	VIF_LOCK_DESTROY();
-	MFC_LOCK_DESTROY();
-	MROUTER_LOCK_DESTROY();
 	break;
 
     default:
diff -ur sys.20081015/netinet/ip_mroute.h sys/netinet/ip_mroute.h
--- sys.20081015/netinet/ip_mroute.h	2008-08-16 16:29:19.000000000 -0700
+++ sys/netinet/ip_mroute.h	2008-11-05 13:21:08.000000000 -0800
@@ -52,6 +52,10 @@
  * bandwidth metering and signaling.
  */
 
+#ifdef VIMAGE
+#include <netinet/pim_var.h>	/* struct pimstat */
+#endif
+
 
 /*
  * Multicast Routing set/getsockopt commands.
@@ -80,6 +84,9 @@
 typedef u_long vifbitmap_t;
 typedef u_short vifi_t;		/* type of a vif index */
 #define ALL_VIFS (vifi_t)-1
+#ifdef VIMAGE
+#define		VIFI_INVALID	((vifi_t) -1)
+#endif /* VIMAGE */
 
 #define	VIFM_SET(n, m)		((m) |= (1 << (n)))
 #define	VIFM_CLR(n, m)		((m) &= ~(1 << (n)))
@@ -205,6 +212,10 @@
 #define BW_UPCALL_THRESHOLD_INTERVAL_MIN_SEC	3
 #define BW_UPCALL_THRESHOLD_INTERVAL_MIN_USEC	0
 
+#ifdef VIMAGE
+#define BW_METER_BUCKETS	1024
+#endif /* VIMAGE */
+
 /*
  * The kernel's multicast routing statistics.
  */
@@ -361,6 +372,62 @@
 extern int	(*ip_mrouter_done)(void);
 extern int	(*mrt_ioctl)(int, caddr_t, int);
 
+#ifdef VIMAGE
+struct vnet_mroute {
+	/* from ip_mroute.c */
+	u_int	_rsvpdebug;
+	u_int	_mrtdebug;
+	struct 	mrtstat _mrtstat;
+	struct	mfc *_mfctable[MFCTBLSIZ];
+	struct	mtx _mrouter_mtx;
+	struct	mtx _mfc_mtx;
+	struct	vif _viftable[MAXVIFS];
+	struct	mtx _vif_mtx;
+	u_char	_nexpire[MFCTBLSIZ];
+	eventhandler_tag _if_detach_event_tag;
+	struct  callout _expire_upcalls_ch;
+	struct	bw_meter *_bw_meter_timers[BW_METER_BUCKETS];
+	struct  callout _bw_meter_ch;
+	struct	bw_upcall _bw_upcalls[BW_UPCALLS_MAX];
+	u_int	_bw_upcalls_n;
+	struct  callout _bw_upcalls_ch;
+	struct	pimstat _pimstat;
+	struct	ifnet _multicast_register_if;
+	vifi_t	_reg_vif_num;
+	vifi_t	_numvifs;
+	int	_pim_assert;
+	uint32_t _mrt_api_config;
+};
+#endif /* VIMAGE */
+
+#define INIT_VNET_MROUTE(vnet) \
+	INIT_FROM_VNET(vnet, VNET_MOD_MROUTE, struct vnet_mroute, vnet_mroute)
+
+#define VNET_MROUTE(sym)  VSYM(vnet_mroute, sym)
+
+#define V_rsvpdebug		VNET_MROUTE(rsvpdebug)
+#define V_mrtdebug		VNET_MROUTE(mrtdebug)
+#define V_mrtstat		VNET_MROUTE(mrtstat)
+#define V_mfctable		VNET_MROUTE(mfctable)
+#define V_mrouter_mtx		VNET_MROUTE(mrouter_mtx)
+#define V_mfc_mtx		VNET_MROUTE(mfc_mtx)
+#define V_viftable		VNET_MROUTE(viftable)
+#define V_vif_mtx		VNET_MROUTE(vif_mtx)
+#define V_nexpire		VNET_MROUTE(nexpire)
+#define V_if_detach_event_tag	VNET_MROUTE(if_detach_event_tag)
+#define V_expire_upcalls_ch	VNET_MROUTE(expire_upcalls_ch)
+#define V_bw_meter_timers	VNET_MROUTE(bw_meter_timers)
+#define V_bw_meter_ch		VNET_MROUTE(bw_meter_ch)
+#define V_bw_upcalls		VNET_MROUTE(bw_upcalls)
+#define V_bw_upcalls_n		VNET_MROUTE(bw_upcalls_n)
+#define V_bw_upcalls_ch		VNET_MROUTE(bw_upcalls_ch)
+#define V_pimstat		VNET_MROUTE(pimstat)
+#define V_multicast_register_if	VNET_MROUTE(multicast_register_if)
+#define V_reg_vif_num		VNET_MROUTE(reg_vif_num)
+#define V_numvifs		VNET_MROUTE(numvifs)
+#define V_pim_assert		VNET_MROUTE(pim_assert)
+#define V_mrt_api_config	VNET_MROUTE(mrt_api_config)
+
 #endif /* _KERNEL */
 
 #endif /* _NETINET_IP_MROUTE_H_ */
diff -ur sys.20081015/netinet/pim_var.h sys/netinet/pim_var.h
--- sys.20081015/netinet/pim_var.h	2007-11-19 06:49:11.000000000 -0800
+++ sys/netinet/pim_var.h	2008-10-28 20:01:22.000000000 -0700
@@ -73,7 +73,9 @@
 #ifdef _KERNEL
 
 void pim_input(struct mbuf *, int);
+#ifdef SYSCTL_DECL
 SYSCTL_DECL(_net_inet_pim);
 #endif
+#endif
 
 #endif /* _NETINET_PIM_VAR_H_ */
diff -ur sys.20081015/netinet/vinet.h sys/netinet/vinet.h
--- sys.20081015/netinet/vinet.h	2007-11-19 09:09:38.000000000 -0800
+++ sys/netinet/vinet.h	2008-11-03 16:04:36.000000000 -0800
@@ -53,6 +53,9 @@
 #include <netinet/tcp_syncache.h>
 #include <netinet/udp.h>
 #include <netinet/udp_var.h>
+#include <netinet/ip_mroute.h>
+#include <netinet/pim.h>
+#include <netinet/pim_var.h>
 
 struct vnet_inet {
 	struct	in_ifaddrhashhead *_in_ifaddrhashtbl;
diff -ur sys.20081015/netinet6/ip6_input.c sys/netinet6/ip6_input.c
--- sys.20081015/netinet6/ip6_input.c	2008-10-15 08:25:28.000000000 -0700
+++ sys/netinet6/ip6_input.c	2008-10-28 20:01:22.000000000 -0700
@@ -192,6 +192,20 @@
 	nd6_init();
 	frag6_init();
 
+	V_ip6_mrouter_ver = 0;
+	V_ip6_mrouter = NULL;
+	bzero(&V_mrt6stat, sizeof(V_mrt6stat));
+	bzero((caddr_t)V_mf6ctable, sizeof(V_mf6ctable));
+	bzero((caddr_t)V_n6expire, sizeof(V_n6expire));
+	bzero((caddr_t)V_mif6table, sizeof(V_mif6table));
+	V_mrt6debug = 0;
+	V_multicast_register_if6 = NULL;
+	V_nummifs = 0;
+	V_reg_mif_num = (mifi_t)-1;
+	bzero(&V_pim6stat, sizeof(V_pim6stat));
+	V_pim6 = 0;
+	bzero((caddr_t)V_upcall_data, sizeof(V_upcall_data));
+
 #ifdef VIMAGE
 	/* Skip global initialization stuff for non-default instances. */
 	if (!IS_DEFAULT_VNET(curvnet))
@@ -507,7 +521,7 @@
 		IN6_LOOKUP_MULTI(ip6->ip6_dst, m->m_pkthdr.rcvif, in6m);
 		if (in6m)
 			ours = 1;
-		else if (!ip6_mrouter) {
+		else if (!V_ip6_mrouter) {
 			V_ip6stat.ip6s_notmember++;
 			V_ip6stat.ip6s_cantforward++;
 			in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard);
@@ -768,7 +782,7 @@
 		 * ip6_mforward() returns a non-zero value, the packet
 		 * must be discarded, else it may be accepted below.
 		 */
-		if (ip6_mrouter && ip6_mforward &&
+		if (V_ip6_mrouter && ip6_mforward &&
 		    ip6_mforward(ip6, m->m_pkthdr.rcvif, m)) {
 			V_ip6stat.ip6s_cantforward++;
 			m_freem(m);
diff -ur sys.20081015/netinet6/ip6_mroute.c sys/netinet6/ip6_mroute.c
--- sys.20081015/netinet6/ip6_mroute.c	2008-10-15 08:25:28.000000000 -0700
+++ sys/netinet6/ip6_mroute.c	2008-11-05 14:34:10.000000000 -0800
@@ -160,14 +160,17 @@
 SYSCTL_DECL(_net_inet6_ip6);
 SYSCTL_NODE(_net_inet6, IPPROTO_PIM, pim, CTLFLAG_RW, 0, "PIM");
 
+#ifndef VIMAGE
 static struct mrt6stat mrt6stat;
-SYSCTL_STRUCT(_net_inet6_ip6, OID_AUTO, mrt6stat, CTLFLAG_RW,
-    &mrt6stat, mrt6stat,
+#endif /* !VIMAGE */
+SYSCTL_V_STRUCT(V_NET, vnet_inet6, _net_inet6_ip6, OID_AUTO, mrt6stat,
+    CTLFLAG_RW, mrt6stat, mrt6stat,
     "Multicast Routing Statistics (struct mrt6stat, netinet6/ip6_mroute.h)");
 
 #define NO_RTE_FOUND	0x1
 #define RTE_FOUND	0x2
 
+#ifndef VIMAGE
 static struct mf6c *mf6ctable[MF6CTBLSIZ];
 SYSCTL_OPAQUE(_net_inet6_ip6, OID_AUTO, mf6ctable, CTLFLAG_RD,
     &mf6ctable, sizeof(mf6ctable), "S,*mf6ctable[MF6CTBLSIZ]",
@@ -180,6 +183,7 @@
 SYSCTL_OPAQUE(_net_inet6_ip6, OID_AUTO, mif6table, CTLFLAG_RD,
     &mif6table, sizeof(mif6table), "S,vif[MAXMIFS]",
     "Multicast Interfaces (struct mif[MAXMIFS], netinet6/ip6_mroute.h)");
+#endif /* !VIMAGE */
 
 #ifdef MRT6DEBUG
 #ifndef VIMAGE
@@ -199,7 +203,9 @@
 
 #ifdef INET
 #ifdef MROUTING
+#ifndef VIMAGE
 extern struct socket *ip_mrouter;
+#endif /* !VIMAGE */
 #endif
 #endif
 
@@ -214,19 +220,23 @@
  * only exist as a placeholder for multicast source
  * verification.
  */
+#ifndef VIMAGE
 static struct ifnet *multicast_register_if6;
+#endif /* !VIMAGE */
 
 #define ENCAP_HOPS 64
 
 /*
  * Private variables.
  */
+#ifndef VIMAGE
 static mifi_t nummifs = 0;
 static mifi_t reg_mif_num = (mifi_t)-1;
 
 static struct pim6stat pim6stat;
-SYSCTL_STRUCT(_net_inet6_pim, PIM6CTL_STATS, stats, CTLFLAG_RD,
-    &pim6stat, pim6stat,
+#endif /* !VIMAGE */
+SYSCTL_V_STRUCT(V_NET, vnet_inet6, _net_inet6_pim, PIM6CTL_STATS, stats,
+    CTLFLAG_RD, pim6stat, pim6stat,
     "PIM Statistics (struct pim6stat, netinet6/pim_var.h)");
 
 #ifndef VIMAGE
@@ -245,9 +255,9 @@
  * Find a route for a given origin IPv6 address and Multicast group address.
  */
 #define MF6CFIND(o, g, rt) do { \
-	struct mf6c *_rt = mf6ctable[MF6CHASH(o,g)]; \
+	struct mf6c *_rt = V_mf6ctable[MF6CHASH(o,g)]; \
 	rt = NULL; \
-	mrt6stat.mrt6s_mfc_lookups++; \
+	V_mrt6stat.mrt6s_mfc_lookups++; \
 	while (_rt) { \
 		if (IN6_ARE_ADDR_EQUAL(&_rt->mf6c_origin.sin6_addr, &(o)) && \
 		    IN6_ARE_ADDR_EQUAL(&_rt->mf6c_mcastgrp.sin6_addr, &(g)) && \
@@ -258,7 +268,7 @@
 		_rt = _rt->mf6c_next; \
 	} \
 	if (rt == NULL) { \
-		mrt6stat.mrt6s_mfc_misses++; \
+		V_mrt6stat.mrt6s_mfc_misses++; \
 	} \
 } while (/*CONSTCOND*/ 0)
 
@@ -291,7 +301,9 @@
 
 #ifdef UPCALL_TIMING
 #define UPCALL_MAX	50
+#ifndef VIMAGE
 static u_long upcall_data[UPCALL_MAX + 1];
+#endif /* !VIMAGE */
 static void collate();
 #endif /* UPCALL_TIMING */
 
@@ -303,7 +315,9 @@
 static int add_m6fc(struct mf6cctl *);
 static int del_m6fc(struct mf6cctl *);
 
-static struct callout expire_upcalls_ch;
+#ifndef VIMAGE
+static struct callout expire_upcalls_ch6;
+#endif /* !VIMAGE */
 
 int X_ip6_mforward(struct ip6_hdr *ip6, struct ifnet *ifp, struct mbuf *m);
 int X_ip6_mrouter_done(void);
@@ -311,19 +325,21 @@
 int X_ip6_mrouter_get(struct socket *so, struct sockopt *sopt);
 int X_mrt6_ioctl(int cmd, caddr_t data);
 
+
 /*
  * Handle MRT setsockopt commands to modify the multicast routing tables.
  */
 int
 X_ip6_mrouter_set(struct socket *so, struct sockopt *sopt)
 {
+	INIT_VNET_INET6(so->so_vnet);
 	int error = 0;
 	int optval;
 	struct mif6ctl mifc;
 	struct mf6cctl mfcc;
 	mifi_t mifi;
 
-	if (so != ip6_mrouter && sopt->sopt_name != MRT6_INIT)
+	if (so != V_ip6_mrouter && sopt->sopt_name != MRT6_INIT)
 		return (EACCES);
 
 	switch (sopt->sopt_name) {
@@ -385,10 +401,10 @@
 int
 X_ip6_mrouter_get(struct socket *so, struct sockopt *sopt)
 {
-	INIT_VNET_INET6(curvnet);
+	INIT_VNET_INET6(so->so_vnet);
 	int error = 0;
 
-	if (so != ip6_mrouter)
+	if (so != V_ip6_mrouter)
 		return (EACCES);
 
 	switch (sopt->sopt_name) {
@@ -421,6 +437,7 @@
 static int
 get_sg_cnt(struct sioc_sg_req6 *req)
 {
+	INIT_VNET_INET6(curvnet);
 	struct mf6c *rt;
 	int s;
 
@@ -446,15 +463,16 @@
 static int
 get_mif6_cnt(struct sioc_mif_req6 *req)
 {
+	INIT_VNET_INET6(curvnet);
 	mifi_t mifi = req->mifi;
 
-	if (mifi >= nummifs)
+	if (mifi >= V_nummifs)
 		return (EINVAL);
 
-	req->icount = mif6table[mifi].m6_pkt_in;
-	req->ocount = mif6table[mifi].m6_pkt_out;
-	req->ibytes = mif6table[mifi].m6_bytes_in;
-	req->obytes = mif6table[mifi].m6_bytes_out;
+	req->icount = V_mif6table[mifi].m6_pkt_in;
+	req->ocount = V_mif6table[mifi].m6_pkt_out;
+	req->ibytes = V_mif6table[mifi].m6_bytes_in;
+	req->obytes = V_mif6table[mifi].m6_bytes_out;
 
 	return (0);
 }
@@ -477,9 +495,11 @@
 static int
 ip6_mrouter_init(struct socket *so, int v, int cmd)
 {
-	INIT_VNET_INET6(curvnet);
+	INIT_VNET_INET6(so->so_vnet);
 
 	V_ip6_mrouter_ver = 0;
+	V_nummifs = 0;
+	V_reg_mif_num = (mifi_t)-1;
 
 #ifdef MRT6DEBUG
 	V_mrt6debug = 0;
@@ -497,20 +517,20 @@
 	if (v != 1)
 		return (ENOPROTOOPT);
 
-	if (ip6_mrouter != NULL)
+	if (V_ip6_mrouter != NULL)
 		return (EADDRINUSE);
 
-	ip6_mrouter = so;
+	V_ip6_mrouter = so;
 	V_ip6_mrouter_ver = cmd;
 
-	bzero((caddr_t)mf6ctable, sizeof(mf6ctable));
-	bzero((caddr_t)n6expire, sizeof(n6expire));
+	bzero((caddr_t)V_mf6ctable, sizeof(V_mf6ctable));
+	bzero((caddr_t)V_n6expire, sizeof(V_n6expire));
 
 	V_pim6 = 0;/* used for stubbing out/in pim stuff */
 
-	callout_init(&expire_upcalls_ch, 0);
-	callout_reset(&expire_upcalls_ch, EXPIRE_TIMEOUT,
-	    expire_upcalls, NULL);
+	callout_init(&V_expire_upcalls_ch6, 0);
+	callout_reset(&V_expire_upcalls_ch6, EXPIRE_TIMEOUT,
+		expire_upcalls, (void *)so->so_vnet);
 
 #ifdef MRT6DEBUG
 	if (V_mrt6debug)
@@ -547,29 +567,29 @@
 	 * XXX: there may be an interface in which the IPv4 multicast
 	 * daemon is not interested...
 	 */
-	if (!ip_mrouter)
+	if (!V_ip_mrouter)
 #endif
 #endif
 	{
-		for (mifi = 0; mifi < nummifs; mifi++) {
-			if (mif6table[mifi].m6_ifp &&
-			    !(mif6table[mifi].m6_flags & MIFF_REGISTER)) {
-				if_allmulti(mif6table[mifi].m6_ifp, 0);
+		for (mifi = 0; mifi < V_nummifs; mifi++) {
+			if (V_mif6table[mifi].m6_ifp &&
+			    !(V_mif6table[mifi].m6_flags & MIFF_REGISTER)) {
+				if_allmulti(V_mif6table[mifi].m6_ifp, 0);
 			}
 		}
 	}
-	bzero((caddr_t)mif6table, sizeof(mif6table));
-	nummifs = 0;
+	bzero((caddr_t)V_mif6table, sizeof(V_mif6table));
+	V_nummifs = 0;
 
 	V_pim6 = 0; /* used to stub out/in pim specific code */
 
-	callout_stop(&expire_upcalls_ch);
+	callout_stop(&V_expire_upcalls_ch6);
 
 	/*
 	 * Free all multicast forwarding cache entries.
 	 */
 	for (i = 0; i < MF6CTBLSIZ; i++) {
-		rt = mf6ctable[i];
+		rt = V_mf6ctable[i];
 		while (rt) {
 			struct mf6c *frt;
 
@@ -586,19 +606,19 @@
 		}
 	}
 
-	bzero((caddr_t)mf6ctable, sizeof(mf6ctable));
+	bzero((caddr_t)V_mf6ctable, sizeof(V_mf6ctable));
 
 	/*
 	 * Reset register interface
 	 */
-	if (reg_mif_num != (mifi_t)-1 && multicast_register_if6 != NULL) {
-		if_detach(multicast_register_if6);
-		if_free(multicast_register_if6);
-		reg_mif_num = (mifi_t)-1;
-		multicast_register_if6 = NULL;
+	if (V_reg_mif_num != (mifi_t)-1 && V_multicast_register_if6 != NULL) {
+		if_detach(V_multicast_register_if6);
+		if_free(V_multicast_register_if6);
+		V_reg_mif_num = (mifi_t)-1;
+		V_multicast_register_if6 = NULL;
 	}
 
-	ip6_mrouter = NULL;
+	V_ip6_mrouter = NULL;
 	V_ip6_mrouter_ver = 0;
 
 	splx(s);
@@ -620,13 +640,14 @@
 add_m6if(struct mif6ctl *mifcp)
 {
 	INIT_VNET_NET(curvnet);
+	INIT_VNET_INET6(curvnet);
 	struct mif6 *mifp;
 	struct ifnet *ifp;
 	int error, s;
 
 	if (mifcp->mif6c_mifi >= MAXMIFS)
 		return (EINVAL);
-	mifp = mif6table + mifcp->mif6c_mifi;
+	mifp = V_mif6table + mifcp->mif6c_mifi;
 	if (mifp->m6_ifp)
 		return (EADDRINUSE); /* XXX: is it appropriate? */
 	if (mifcp->mif6c_pifi == 0 || mifcp->mif6c_pifi > V_if_index)
@@ -634,14 +655,14 @@
 	ifp = ifnet_byindex(mifcp->mif6c_pifi);
 
 	if (mifcp->mif6c_flags & MIFF_REGISTER) {
-		if (reg_mif_num == (mifi_t)-1) {
+		if (V_reg_mif_num == (mifi_t)-1) {
 			ifp = if_alloc(IFT_OTHER);
 
 			if_initname(ifp, "register_mif", 0);
 			ifp->if_flags |= IFF_LOOPBACK;
 			if_attach(ifp);
-			multicast_register_if6 = ifp;
-			reg_mif_num = mifcp->mif6c_mifi;
+			V_multicast_register_if6 = ifp;
+			V_reg_mif_num = mifcp->mif6c_mifi;
 			/*
 			 * it is impossible to guess the ifindex of the
 			 * register interface.  So mif6c_pifi is automatically
@@ -649,7 +670,7 @@
 			 */
 			mifcp->mif6c_pifi = ifp->if_index;
 		} else {
-			ifp = multicast_register_if6;
+			ifp = V_multicast_register_if6;
 		}
 
 	} /* if REGISTER */
@@ -676,9 +697,9 @@
 	mifp->m6_bytes_out = 0;
 	splx(s);
 
-	/* Adjust nummifs up if the mifi is higher than nummifs */
-	if (nummifs <= mifcp->mif6c_mifi)
-		nummifs = mifcp->mif6c_mifi + 1;
+	/* Adjust V_nummifs up if the mifi is higher than V_nummifs */
+	if (V_nummifs <= mifcp->mif6c_mifi)
+		V_nummifs = mifcp->mif6c_mifi + 1;
 
 #ifdef MRT6DEBUG
 	if (V_mrt6debug)
@@ -697,12 +718,13 @@
 static int
 del_m6if(mifi_t *mifip)
 {
-	struct mif6 *mifp = mif6table + *mifip;
+	INIT_VNET_INET6(curvnet);
+	struct mif6 *mifp = V_mif6table + *mifip;
 	mifi_t mifi;
 	struct ifnet *ifp;
 	int s;
 
-	if (*mifip >= nummifs)
+	if (*mifip >= V_nummifs)
 		return (EINVAL);
 	if (mifp->m6_ifp == NULL)
 		return (EINVAL);
@@ -718,28 +740,28 @@
 
 		if_allmulti(ifp, 0);
 	} else {
-		if (reg_mif_num != (mifi_t)-1 &&
-		    multicast_register_if6 != NULL) {
-			if_detach(multicast_register_if6);
-			if_free(multicast_register_if6);
-			reg_mif_num = (mifi_t)-1;
-			multicast_register_if6 = NULL;
+		if (V_reg_mif_num != (mifi_t)-1 &&
+		    V_multicast_register_if6 != NULL) {
+			if_detach(V_multicast_register_if6);
+			if_free(V_multicast_register_if6);
+			V_reg_mif_num = (mifi_t)-1;
+			V_multicast_register_if6 = NULL;
 		}
 	}
 
 	bzero((caddr_t)mifp, sizeof(*mifp));
 
-	/* Adjust nummifs down */
-	for (mifi = nummifs; mifi > 0; mifi--)
-		if (mif6table[mifi - 1].m6_ifp)
+	/* Adjust V_nummifs down */
+	for (mifi = V_nummifs; mifi > 0; mifi--)
+		if (V_mif6table[mifi - 1].m6_ifp)
 			break;
-	nummifs = mifi;
+	V_nummifs = mifi;
 
 	splx(s);
 
 #ifdef MRT6DEBUG
 	if (V_mrt6debug)
-		log(LOG_DEBUG, "del_m6if %d, nummifs %d\n", *mifip, nummifs);
+		log(LOG_DEBUG, "del_m6if %d, nummifs %d\n", *mifip, V_nummifs);
 #endif
 
 	return (0);
@@ -787,7 +809,7 @@
 	s = splnet();
 	hash = MF6CHASH(mfccp->mf6cc_origin.sin6_addr,
 			mfccp->mf6cc_mcastgrp.sin6_addr);
-	for (rt = mf6ctable[hash], nstl = 0; rt; rt = rt->mf6c_next) {
+	for (rt = V_mf6ctable[hash], nstl = 0; rt; rt = rt->mf6c_next) {
 		if (IN6_ARE_ADDR_EQUAL(&rt->mf6c_origin.sin6_addr,
 				       &mfccp->mf6cc_origin.sin6_addr) &&
 		    IN6_ARE_ADDR_EQUAL(&rt->mf6c_mcastgrp.sin6_addr,
@@ -825,7 +847,7 @@
 			rt->mf6c_wrong_if   = 0;
 
 			rt->mf6c_expire = 0;	/* Don't clean this guy up */
-			n6expire[hash]--;
+			V_n6expire[hash]--;
 
 			/* free packets Qed at the end of this entry */
 			for (rte = rt->mf6c_stall; rte != NULL; ) {
@@ -856,7 +878,7 @@
 			mfccp->mf6cc_parent);
 #endif
 
-		for (rt = mf6ctable[hash]; rt; rt = rt->mf6c_next) {
+		for (rt = V_mf6ctable[hash]; rt; rt = rt->mf6c_next) {
 
 			if (IN6_ARE_ADDR_EQUAL(&rt->mf6c_origin.sin6_addr,
 					       &mfccp->mf6cc_origin.sin6_addr)&&
@@ -873,7 +895,7 @@
 				rt->mf6c_wrong_if   = 0;
 
 				if (rt->mf6c_expire)
-					n6expire[hash]--;
+					V_n6expire[hash]--;
 				rt->mf6c_expire	   = 0;
 			}
 		}
@@ -899,8 +921,8 @@
 			rt->mf6c_stall = NULL;
 
 			/* link into table */
-			rt->mf6c_next  = mf6ctable[hash];
-			mf6ctable[hash] = rt;
+			rt->mf6c_next  = V_mf6ctable[hash];
+			V_mf6ctable[hash] = rt;
 		}
 	}
 	splx(s);
@@ -914,6 +936,7 @@
 static void
 collate(struct timeval *t)
 {
+	INIT_VNET_INET6(curvnet);
 	u_long d;
 	struct timeval tp;
 	u_long delta;
@@ -928,7 +951,7 @@
 		if (d > UPCALL_MAX)
 			d = UPCALL_MAX;
 
-		++upcall_data[d];
+		++V_upcall_data[d];
 	}
 }
 #endif /* UPCALL_TIMING */
@@ -962,7 +985,7 @@
 
 	s = splnet();
 
-	nptr = &mf6ctable[hash];
+	nptr = &V_mf6ctable[hash];
 	while ((rt = *nptr) != NULL) {
 		if (IN6_ARE_ADDR_EQUAL(&origin.sin6_addr,
 				       &rt->mf6c_origin.sin6_addr) &&
@@ -1097,7 +1120,7 @@
 		GET_TIME(tp);
 #endif /* UPCALL_TIMING */
 
-		mrt6stat.mrt6s_no_route++;
+		V_mrt6stat.mrt6s_no_route++;
 #ifdef MRT6DEBUG
 		if (V_mrt6debug & (DEBUG_FORWARD | DEBUG_MFC))
 			log(LOG_DEBUG, "ip6_mforward: no rte s %s g %s\n",
@@ -1131,7 +1154,7 @@
 
 		/* is there an upcall waiting for this packet? */
 		hash = MF6CHASH(ip6->ip6_src, ip6->ip6_dst);
-		for (rt = mf6ctable[hash]; rt; rt = rt->mf6c_next) {
+		for (rt = V_mf6ctable[hash]; rt; rt = rt->mf6c_next) {
 			if (IN6_ARE_ADDR_EQUAL(&ip6->ip6_src,
 					       &rt->mf6c_origin.sin6_addr) &&
 			    IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst,
@@ -1205,8 +1228,8 @@
 				    "getting the iif info in the kernel\n");
 #endif
 
-			for (mifp = mif6table, mifi = 0;
-			     mifi < nummifs && mifp->m6_ifp != ifp;
+			for (mifp = V_mif6table, mifi = 0;
+			     mifi < V_nummifs && mifp->m6_ifp != ifp;
 			     mifp++, mifi++)
 				;
 
@@ -1221,10 +1244,10 @@
 				break;
 			}
 
-			if (socket_send(ip6_mrouter, mm, &sin6) < 0) {
+			if (socket_send(V_ip6_mrouter, mm, &sin6) < 0) {
 				log(LOG_WARNING, "ip6_mforward: ip6_mrouter "
 				    "socket queue full\n");
-				mrt6stat.mrt6s_upq_sockfull++;
+				V_mrt6stat.mrt6s_upq_sockfull++;
 				free(rte, M_MRTABLE6);
 				m_freem(mb0);
 				free(rt, M_MRTABLE6);
@@ -1232,7 +1255,7 @@
 				return (ENOBUFS);
 			}
 
-			mrt6stat.mrt6s_upcalls++;
+			V_mrt6stat.mrt6s_upcalls++;
 
 			/* insert new entry at head of hash chain */
 			bzero(rt, sizeof(*rt));
@@ -1243,12 +1266,12 @@
 			rt->mf6c_mcastgrp.sin6_len = sizeof(struct sockaddr_in6);
 			rt->mf6c_mcastgrp.sin6_addr = ip6->ip6_dst;
 			rt->mf6c_expire = UPCALL_EXPIRE;
-			n6expire[hash]++;
+			V_n6expire[hash]++;
 			rt->mf6c_parent = MF6C_INCOMPLETE_PARENT;
 
 			/* link into table */
-			rt->mf6c_next  = mf6ctable[hash];
-			mf6ctable[hash] = rt;
+			rt->mf6c_next  = V_mf6ctable[hash];
+			V_mf6ctable[hash] = rt;
 			/* Add this entry to the end of the queue */
 			rt->mf6c_stall = rte;
 		} else {
@@ -1258,7 +1281,7 @@
 
 			for (p = &rt->mf6c_stall; *p != NULL; p = &(*p)->next)
 				if (++npkts > MAX_UPQ6) {
-					mrt6stat.mrt6s_upq_ovflw++;
+					V_mrt6stat.mrt6s_upq_ovflw++;
 					free(rte, M_MRTABLE6);
 					m_freem(mb0);
 					splx(s);
@@ -1289,7 +1312,7 @@
 static void
 expire_upcalls(void *unused)
 {
-	INIT_VNET_INET6(curvnet);
+	INIT_VNET_INET6( (struct vnet*)unused );
 	struct rtdetq *rte;
 	struct mf6c *mfc, **nptr;
 	int i;
@@ -1297,9 +1320,9 @@
 
 	s = splnet();
 	for (i = 0; i < MF6CTBLSIZ; i++) {
-		if (n6expire[i] == 0)
+		if (V_n6expire[i] == 0)
 			continue;
-		nptr = &mf6ctable[i];
+		nptr = &V_mf6ctable[i];
 		while ((mfc = *nptr) != NULL) {
 			rte = mfc->mf6c_stall;
 			/*
@@ -1329,8 +1352,8 @@
 					free(rte, M_MRTABLE6);
 					rte = n;
 				} while (rte != NULL);
-				mrt6stat.mrt6s_cache_cleanups++;
-				n6expire[i]--;
+				V_mrt6stat.mrt6s_cache_cleanups++;
+				V_n6expire[i]--;
 
 				*nptr = mfc->mf6c_next;
 				free(mfc, M_MRTABLE6);
@@ -1339,9 +1362,9 @@
 			}
 		}
 	}
+	callout_reset(&V_expire_upcalls_ch6, EXPIRE_TIMEOUT,
+	    expire_upcalls, unused);
 	splx(s);
-	callout_reset(&expire_upcalls_ch, EXPIRE_TIMEOUT,
-	    expire_upcalls, NULL);
 }
 
 /*
@@ -1377,16 +1400,16 @@
 	 * for its origin.
 	 */
 	mifi = rt->mf6c_parent;
-	if ((mifi >= nummifs) || (mif6table[mifi].m6_ifp != ifp)) {
+	if ((mifi >= V_nummifs) || (V_mif6table[mifi].m6_ifp != ifp)) {
 		/* came in the wrong interface */
 #ifdef MRT6DEBUG
 		if (V_mrt6debug & DEBUG_FORWARD)
 			log(LOG_DEBUG,
 			    "wrong if: ifid %d mifi %d mififid %x\n",
 			    ifp->if_index, mifi,
-			    mif6table[mifi].m6_ifp->if_index);
+			    V_mif6table[mifi].m6_ifp->if_index);
 #endif
-		mrt6stat.mrt6s_wrong_if++;
+		V_mrt6stat.mrt6s_wrong_if++;
 		rt->mf6c_wrong_if++;
 		/*
 		 * If we are doing PIM processing, and we are forwarding
@@ -1394,7 +1417,7 @@
 		 * routing daemon.
 		 */
 		/* have to make sure this is a valid mif */
-		if (mifi < nummifs && mif6table[mifi].m6_ifp)
+		if (mifi < V_nummifs && V_mif6table[mifi].m6_ifp)
 			if (V_pim6 && (m->m_flags & M_LOOP) == 0) {
 				/*
 				 * Check the M_LOOP flag to avoid an
@@ -1440,8 +1463,8 @@
 					return (EINVAL);
 				}
 
-				for (mifp = mif6table, iif = 0;
-				     iif < nummifs && mifp &&
+				for (mifp = V_mif6table, iif = 0;
+				     iif < V_nummifs && mifp &&
 					     mifp->m6_ifp != ifp;
 				     mifp++, iif++)
 					;
@@ -1459,14 +1482,14 @@
 					break;
 				}
 
-				mrt6stat.mrt6s_upcalls++;
+				V_mrt6stat.mrt6s_upcalls++;
 
-				if (socket_send(ip6_mrouter, mm, &sin6) < 0) {
+				if (socket_send(V_ip6_mrouter, mm, &sin6) < 0) {
 #ifdef MRT6DEBUG
 					if (V_mrt6debug)
 						log(LOG_WARNING, "mdq, ip6_mrouter socket queue full\n");
 #endif
-					++mrt6stat.mrt6s_upq_sockfull;
+					++V_mrt6stat.mrt6s_upq_sockfull;
 					return (ENOBUFS);
 				}	/* if socket Q full */
 			}		/* if PIM */
@@ -1476,11 +1499,11 @@
 	/* If I sourced this packet, it counts as output, else it was input. */
 	if (m->m_pkthdr.rcvif == NULL) {
 		/* XXX: is rcvif really NULL when output?? */
-		mif6table[mifi].m6_pkt_out++;
-		mif6table[mifi].m6_bytes_out += plen;
+		V_mif6table[mifi].m6_pkt_out++;
+		V_mif6table[mifi].m6_bytes_out += plen;
 	} else {
-		mif6table[mifi].m6_pkt_in++;
-		mif6table[mifi].m6_bytes_in += plen;
+		V_mif6table[mifi].m6_pkt_in++;
+		V_mif6table[mifi].m6_bytes_in += plen;
 	}
 	rt->mf6c_pkt_cnt++;
 	rt->mf6c_byte_cnt += plen;
@@ -1496,7 +1519,7 @@
 		V_ip6stat.ip6s_badscope++;
 		return (error);
 	}
-	for (mifp = mif6table, mifi = 0; mifi < nummifs; mifp++, mifi++) {
+	for (mifp = V_mif6table, mifi = 0; mifi < V_nummifs; mifp++, mifi++) {
 		if (IF_ISSET(mifi, &rt->mf6c_ifset)) {
 			/*
 			 * check if the outgoing packet is going to break
@@ -1504,12 +1527,12 @@
 			 * XXX For packets through PIM register tunnel
 			 * interface, we believe a routing daemon.
 			 */
-			if (!(mif6table[rt->mf6c_parent].m6_flags &
+			if (!(V_mif6table[rt->mf6c_parent].m6_flags &
 			      MIFF_REGISTER) &&
-			    !(mif6table[mifi].m6_flags & MIFF_REGISTER)) {
-				if (in6_setscope(&src0, mif6table[mifi].m6_ifp,
+			    !(V_mif6table[mifi].m6_flags & MIFF_REGISTER)) {
+				if (in6_setscope(&src0, V_mif6table[mifi].m6_ifp,
 				    &oszone) ||
-				    in6_setscope(&dst0, mif6table[mifi].m6_ifp,
+				    in6_setscope(&dst0, V_mif6table[mifi].m6_ifp,
 				    &odzone) ||
 				    iszone != oszone ||
 				    idzone != odzone) {
@@ -1575,7 +1598,7 @@
 #ifdef MRT6DEBUG
 		if (V_mrt6debug & DEBUG_XMIT)
 			log(LOG_DEBUG, "phyint_send on mif %d err %d\n",
-			    mifp - mif6table, error);
+			    mifp - V_mif6table, error);
 #endif
 		splx(s);
 		return;
@@ -1611,7 +1634,7 @@
 #ifdef MRT6DEBUG
 		if (V_mrt6debug & DEBUG_XMIT)
 			log(LOG_DEBUG, "phyint_send on mif %d err %d\n",
-			    mifp - mif6table, error);
+			    mifp - V_mif6table, error);
 #endif
 	} else {
 		/*
@@ -1659,7 +1682,7 @@
 		    ip6_sprintf(ip6bufd, &ip6->ip6_dst));
 	}
 #endif
-	++pim6stat.pim6s_snd_registers;
+	++V_pim6stat.pim6s_snd_registers;
 
 	/* Make a copy of the packet to send to the user level process */
 	MGETHDR(mm, M_DONTWAIT, MT_HEADER);
@@ -1691,18 +1714,18 @@
 	im6->im6_msgtype      = MRT6MSG_WHOLEPKT;
 	im6->im6_mbz          = 0;
 
-	im6->im6_mif = mif - mif6table;
+	im6->im6_mif = mif - V_mif6table;
 
 	/* iif info is not given for reg. encap.n */
-	mrt6stat.mrt6s_upcalls++;
+	V_mrt6stat.mrt6s_upcalls++;
 
-	if (socket_send(ip6_mrouter, mm, &sin6) < 0) {
+	if (socket_send(V_ip6_mrouter, mm, &sin6) < 0) {
 #ifdef MRT6DEBUG
 		if (V_mrt6debug)
 			log(LOG_WARNING,
 			    "register_send: ip6_mrouter socket queue full\n");
 #endif
-		++mrt6stat.mrt6s_upq_sockfull;
+		++V_mrt6stat.mrt6s_upq_sockfull;
 		return (ENOBUFS);
 	}
 	return (0);
@@ -1726,7 +1749,7 @@
 	int minlen;
 	int off = *offp;
 
-	++pim6stat.pim6s_rcv_total;
+	++V_pim6stat.pim6s_rcv_total;
 
 	ip6 = mtod(m, struct ip6_hdr *);
 	pimlen = m->m_pkthdr.len - *offp;
@@ -1735,7 +1758,7 @@
 	 * Validate lengths
 	 */
 	if (pimlen < PIM_MINLEN) {
-		++pim6stat.pim6s_rcv_tooshort;
+		++V_pim6stat.pim6s_rcv_tooshort;
 #ifdef MRT6DEBUG
 		if (V_mrt6debug & DEBUG_PIM)
 			log(LOG_DEBUG,"pim6_input: PIM packet too short\n");
@@ -1768,7 +1791,7 @@
 #else
 	IP6_EXTHDR_GET(pim, struct pim *, m, off, minlen);
 	if (pim == NULL) {
-		pim6stat.pim6s_rcv_tooshort++;
+		V_pim6stat.pim6s_rcv_tooshort++;
 		return (IPPROTO_DONE);
 	}
 #endif
@@ -1788,7 +1811,7 @@
 			cksumlen = pimlen;
 
 		if (in6_cksum(m, IPPROTO_PIM, off, cksumlen)) {
-			++pim6stat.pim6s_rcv_badsum;
+			++V_pim6stat.pim6s_rcv_badsum;
 #ifdef MRT6DEBUG
 			if (V_mrt6debug & DEBUG_PIM)
 				log(LOG_DEBUG,
@@ -1802,7 +1825,7 @@
 
 	/* PIM version check */
 	if (pim->pim_ver != PIM_VERSION) {
-		++pim6stat.pim6s_rcv_badversion;
+		++V_pim6stat.pim6s_rcv_badversion;
 #ifdef MRT6DEBUG
 		log(LOG_ERR,
 		    "pim6_input: incorrect version %d, expecting %d\n",
@@ -1828,14 +1851,14 @@
 		char ip6bufs[INET6_ADDRSTRLEN], ip6bufd[INET6_ADDRSTRLEN];
 #endif
 
-		++pim6stat.pim6s_rcv_registers;
+		++V_pim6stat.pim6s_rcv_registers;
 
-		if ((reg_mif_num >= nummifs) || (reg_mif_num == (mifi_t) -1)) {
+		if ((V_reg_mif_num >= V_nummifs) || (V_reg_mif_num == (mifi_t) -1)) {
 #ifdef MRT6DEBUG
 			if (V_mrt6debug & DEBUG_PIM)
 				log(LOG_DEBUG,
 				    "pim6_input: register mif not set: %d\n",
-				    reg_mif_num);
+				    V_reg_mif_num);
 #endif
 			m_freem(m);
 			return (IPPROTO_DONE);
@@ -1850,8 +1873,8 @@
 		 * Validate length
 		 */
 		if (pimlen < PIM6_REG_MINLEN) {
-			++pim6stat.pim6s_rcv_tooshort;
-			++pim6stat.pim6s_rcv_badregisters;
+			++V_pim6stat.pim6s_rcv_tooshort;
+			++V_pim6stat.pim6s_rcv_badregisters;
 #ifdef MRT6DEBUG
 			log(LOG_ERR,
 			    "pim6_input: register packet size too "
@@ -1875,7 +1898,7 @@
 
 		/* verify the version number of the inner packet */
 		if ((eip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) {
-			++pim6stat.pim6s_rcv_badregisters;
+			++V_pim6stat.pim6s_rcv_badregisters;
 #ifdef MRT6DEBUG
 			log(LOG_DEBUG, "pim6_input: invalid IP version (%d) "
 			    "of the inner packet\n",
@@ -1887,7 +1910,7 @@
 
 		/* verify the inner packet is destined to a mcast group */
 		if (!IN6_IS_ADDR_MULTICAST(&eip6->ip6_dst)) {
-			++pim6stat.pim6s_rcv_badregisters;
+			++V_pim6stat.pim6s_rcv_badregisters;
 #ifdef MRT6DEBUG
 			if (V_mrt6debug & DEBUG_PIM)
 				log(LOG_DEBUG,
@@ -1924,11 +1947,11 @@
 			    "src %s, dst %s, mif %d\n",
 			    ip6_sprintf(ip6bufs, &eip6->ip6_src),
 			    ip6_sprintf(ip6bufd, &eip6->ip6_dst),
-			    reg_mif_num);
+			    V_reg_mif_num);
 		}
 #endif
 
-		rc = if_simloop(mif6table[reg_mif_num].m6_ifp, m,
+		rc = if_simloop(V_mif6table[V_reg_mif_num].m6_ifp, m,
 				dst.sin6_family, 0);
 
 		/* prepare the register head to send to the mrouting daemon */
diff -ur sys.20081015/netinet6/ip6_mroute.h sys/netinet6/ip6_mroute.h
--- sys.20081015/netinet6/ip6_mroute.h	2008-10-15 08:25:28.000000000 -0700
+++ sys/netinet6/ip6_mroute.h	2008-11-05 13:21:56.000000000 -0800
@@ -266,6 +266,7 @@
 extern int	(*ip6_mrouter_get)(struct socket *so, struct sockopt *sopt);
 extern int	(*ip6_mrouter_done)(void);
 extern int	(*mrt6_ioctl)(int, caddr_t);
+
 #endif /* _KERNEL */
 
 #endif /* !_NETINET6_IP6_MROUTE_H_ */
diff -ur sys.20081015/netinet6/ip6_output.c sys/netinet6/ip6_output.c
--- sys.20081015/netinet6/ip6_output.c	2008-10-15 08:25:28.000000000 -0700
+++ sys/netinet6/ip6_output.c	2008-10-28 20:01:22.000000000 -0700
@@ -744,7 +744,7 @@
 			 * above, will be forwarded by the ip6_input() routine,
 			 * if necessary.
 			 */
-			if (ip6_mrouter && (flags & IPV6_FORWARDING) == 0) {
+			if (V_ip6_mrouter && (flags & IPV6_FORWARDING) == 0) {
 				/*
 				 * XXX: ip6_mforward expects that rcvif is NULL
 				 * when it is called from the originating path.
diff -ur sys.20081015/netinet6/ip6_var.h sys/netinet6/ip6_var.h
--- sys.20081015/netinet6/ip6_var.h	2008-10-15 08:25:28.000000000 -0700
+++ sys/netinet6/ip6_var.h	2008-10-28 20:01:22.000000000 -0700
@@ -292,8 +292,8 @@
 extern int	ip6_v6only;
 #endif
 
-extern struct socket *ip6_mrouter;	/* multicast routing daemon */
 #ifndef VIMAGE
+extern struct socket *ip6_mrouter;	/* multicast routing daemon */
 extern int	ip6_sendredirects;	/* send IP redirects when forwarding? */
 extern int	ip6_maxfragpackets; /* Maximum packets in reassembly queue */
 extern int	ip6_maxfrags;	/* Maximum fragments in reassembly queue */
diff -ur sys.20081015/netinet6/mld6.c sys/netinet6/mld6.c
--- sys.20081015/netinet6/mld6.c	2008-10-15 08:25:28.000000000 -0700
+++ sys/netinet6/mld6.c	2008-10-28 20:01:22.000000000 -0700
@@ -518,7 +518,7 @@
 	 * Request loopback of the report if we are acting as a multicast
 	 * router, so that the process-level routing daemon can hear it.
 	 */
-	im6o.im6o_multicast_loop = (ip6_mrouter != NULL);
+	im6o.im6o_multicast_loop = (V_ip6_mrouter != NULL);
 
 	/* increment output statictics */
 	V_icmp6stat.icp6s_outhist[type]++;
diff -ur sys.20081015/netinet6/raw_ip6.c sys/netinet6/raw_ip6.c
--- sys.20081015/netinet6/raw_ip6.c	2008-10-15 08:25:28.000000000 -0700
+++ sys/netinet6/raw_ip6.c	2008-10-28 20:01:22.000000000 -0700
@@ -129,7 +129,9 @@
 /*
  * Hooks for multicast forwarding.
  */
+#ifndef VIMAGE
 struct socket *ip6_mrouter = NULL;
+#endif
 int (*ip6_mrouter_set)(struct socket *, struct sockopt *);
 int (*ip6_mrouter_get)(struct socket *, struct sockopt *);
 int (*ip6_mrouter_done)(void);
@@ -599,12 +601,13 @@
 rip6_detach(struct socket *so)
 {
 	INIT_VNET_INET(so->so_vnet);
+	INIT_VNET_INET6(so->so_vnet);
 	struct inpcb *inp;
 
 	inp = sotoinpcb(so);
 	KASSERT(inp != NULL, ("rip6_detach: inp == NULL"));
 
-	if (so == ip6_mrouter && ip6_mrouter_done)
+	if (so == V_ip6_mrouter && ip6_mrouter_done)
 		ip6_mrouter_done();
 	/* xxx: RSVP */
 	INP_INFO_WLOCK(&V_ripcbinfo);
diff -ur sys.20081015/netinet6/vinet6.h sys/netinet6/vinet6.h
--- sys.20081015/netinet6/vinet6.h	2008-10-15 08:25:28.000000000 -0700
+++ sys/netinet6/vinet6.h	2008-10-29 12:58:52.000000000 -0700
@@ -43,6 +43,8 @@
 #include <netinet6/scope6_var.h>
 #include <netinet6/in6_ifattach.h>
 #include <netinet6/nd6.h>
+#include <netinet6/ip6_mroute.h>
+#include <netinet6/pim6_var.h> /* struct pim6stat */
 
 #define INIT_VNET_INET6(vnet) \
 	INIT_FROM_VNET(vnet, VNET_MOD_INET6, \
@@ -95,6 +97,7 @@
 	//int				_icmp6_nodeinfo;
 
 	int 				_ip6_forwarding;
+	struct socket *			_ip6_mrouter;
 	int				_ip6_sendredirects;
 	int				_ip6_defhlim;
 	int				_ip6_defmcasthlim;
@@ -149,14 +152,25 @@
 	u_int32_t			_ip6_temp_preferred_lifetime;
 	u_int32_t			_ip6_temp_valid_lifetime;
 
-	int				_ip6_mrouter_ver;
-	int				_pim6;
-	u_int				_mrt6debug;
-
 	int				_ip6_temp_regen_advance;
 	int				_ip6_use_defzone;
 
 	struct ip6_pktopts		_ip6_opts;
+
+	/* from ip6_mroute.c */
+	int				_ip6_mrouter_ver; /* = 0; */
+	struct mrt6stat			_mrt6stat;
+	struct mf6c *			_mf6ctable[MF6CTBLSIZ];
+	u_char				_n6expire[MF6CTBLSIZ];
+	struct mif6 			_mif6table[MAXMIFS];
+	u_int				_mrt6debug;
+	struct ifnet *			_multicast_register_if6;
+	mifi_t 				_nummifs; /* = 0; */
+	mifi_t 				_reg_mif_num; /* = (mifi_t)-1; */
+	struct pim6stat			_pim6stat;
+	int 				_pim6;
+	u_long				_upcall_data[51];
+	struct callout			_expire_upcalls_ch6;
 };
 #endif
 
@@ -206,6 +220,7 @@
 //#define V_icmp6_nodeinfo		VNET_INET6(icmp6_nodeinfo)
 
 #define V_ip6_forwarding		VNET_INET6(ip6_forwarding)
+#define V_ip6_mrouter			VNET_INET6(ip6_mrouter)
 #define V_ip6_sendredirects		VNET_INET6(ip6_sendredirects)
 #define V_ip6_defhlim			VNET_INET6(ip6_defhlim)
 #define V_ip6_defmcasthlim		VNET_INET6(ip6_defmcasthlim)
@@ -260,13 +275,24 @@
 #define V_ip6_temp_preferred_lifetime	VNET_INET6(ip6_temp_preferred_lifetime)
 #define V_ip6_temp_valid_lifetime	VNET_INET6(ip6_temp_valid_lifetime)
 
-#define V_ip6_mrouter_ver		VNET_INET6(ip6_mrouter_ver)
-#define V_pim6				VNET_INET6(pim6)
-#define V_mrt6debug			VNET_INET6(mrt6debug)
 #define V_ip6_temp_regen_advance	VNET_INET6(ip6_temp_regen_advance)
 
 #define V_ip6_use_defzone		VNET_INET6(ip6_use_defzone)
 
 #define V_ip6_opts			VNET_INET6(ip6_opts)
 
+#define V_ip6_mrouter_ver		VNET_INET6(ip6_mrouter_ver)
+#define V_mrt6stat			VNET_INET6(mrt6stat)
+#define V_mf6ctable			VNET_INET6(mf6ctable)
+#define V_n6expire			VNET_INET6(n6expire)
+#define V_mif6table			VNET_INET6(mif6table)
+#define V_mrt6debug			VNET_INET6(mrt6debug)
+#define V_multicast_register_if6	VNET_INET6(multicast_register_if6)
+#define V_nummifs			VNET_INET6(nummifs)
+#define V_reg_mif_num			VNET_INET6(reg_mif_num)
+#define V_pim6stat			VNET_INET6(pim6stat)
+#define V_pim6				VNET_INET6(pim6)
+#define V_upcall_data			VNET_INET6(upcall_data)
+#define V_expire_upcalls_ch6		VNET_INET6(expire_upcalls_ch6)
+
 #endif /* !_NETINET6_VINET6_H_ */
diff -ur sys.20081015/netipsec/keysock.c sys/netipsec/keysock.c
--- sys.20081015/netipsec/keysock.c	2008-10-15 08:25:29.000000000 -0700
+++ sys/netipsec/keysock.c	2008-10-29 07:57:18.000000000 -0700
@@ -429,8 +429,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++;
+		V_key_cb.key_count++;
+	V_key_cb.any_count++;
 	soisconnected(so);
 	so->so_options |= SO_USELOOPBACK;
 
diff -ur sys.20081015/sys/vimage.h sys/sys/vimage.h
--- sys.20081015/sys/vimage.h	2008-10-15 08:25:30.000000000 -0700
+++ sys/sys/vimage.h	2008-11-04 13:56:18.000000000 -0800
@@ -77,6 +77,7 @@
 #define VNET_MOD_IPX		 9
 #define VNET_MOD_ATALK		10
 #define VNET_MOD_DIVERT		11
+#define VNET_MOD_MROUTE		12
 /* stateless modules */
 #define VNET_MOD_NG_WORMHOLE	19
 #define VNET_MOD_NG_ETHER	20
@@ -103,6 +104,7 @@
 #define V_MOD_vnet_pf		VNET_MOD_PF
 #define V_MOD_vnet_gif		VNET_MOD_GIF
 #define V_MOD_vnet_ipsec	VNET_MOD_IPSEC
+#define V_MOD_vnet_mroute	VNET_MOD_MROUTE
 
 #define V_MOD_vprocg		0
 #define V_MOD_vcpu		0
help

Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?0DF156EE7414494187B087A3C279BDB40AF14C23>