svn commit: r193731 - in head: . sys/kern sys/net sys/netgraph sys/netinet sys/netinet6 sys/netipsec sys/sys

Marko Zec zec at FreeBSD.org
Mon Jun 8 17:15:42 UTC 2009


Author: zec
Date: Mon Jun  8 17:15:40 2009
New Revision: 193731
URL: http://svn.freebsd.org/changeset/base/193731

Log:
  Introduce an infrastructure for dismantling vnet instances.
  
  Vnet modules and protocol domains may now register destructor
  functions to clean up and release per-module state.  The destructor
  mechanisms can be triggered by invoking "vimage -d", or a future
  equivalent command which will be provided via the new jail framework.
  
  While this patch introduces numerous placeholder destructor functions,
  many of those are currently incomplete, thus leaking memory or (even
  worse) failing to stop all running timers.  Many of such issues are
  already known and will be incrementaly fixed over the next weeks in
  smaller incremental commits.
  
  Apart from introducing new fields in structs ifnet, domain, protosw
  and vnet_net, which requires the kernel and modules to be rebuilt, this
  change should have no impact on nooptions VIMAGE builds, since vnet
  destructors can only be called in VIMAGE kernels.  Moreover,
  destructor functions should be in general compiled in only in
  options VIMAGE builds, except for kernel modules which can be safely
  kldunloaded at run time.
  
  Bump __FreeBSD_version to 800097.
  Reviewed by:	bz, julian
  Approved by:	rwatson, kib (re), julian (mentor)

Modified:
  head/UPDATING
  head/sys/kern/kern_vimage.c
  head/sys/kern/uipc_domain.c
  head/sys/net/if.c
  head/sys/net/if_gif.c
  head/sys/net/if_loop.c
  head/sys/net/if_var.h
  head/sys/net/route.c
  head/sys/net/vnet.h
  head/sys/netgraph/ng_base.c
  head/sys/netinet/in_proto.c
  head/sys/netinet/in_rmx.c
  head/sys/netinet/ip_var.h
  head/sys/netinet/raw_ip.c
  head/sys/netinet/tcp_hostcache.c
  head/sys/netinet/tcp_subr.c
  head/sys/netinet/tcp_syncache.c
  head/sys/netinet/tcp_syncache.h
  head/sys/netinet/tcp_timewait.c
  head/sys/netinet/tcp_var.h
  head/sys/netinet/udp_usrreq.c
  head/sys/netinet/udp_var.h
  head/sys/netinet6/in6_proto.c
  head/sys/netinet6/in6_rmx.c
  head/sys/netinet6/ip6_input.c
  head/sys/netinet6/ip6_var.h
  head/sys/netinet6/ip6protosw.h
  head/sys/netinet6/nd6.c
  head/sys/netinet6/nd6.h
  head/sys/netipsec/ipsec.c
  head/sys/netipsec/key.c
  head/sys/netipsec/key.h
  head/sys/netipsec/keysock.c
  head/sys/sys/domain.h
  head/sys/sys/param.h
  head/sys/sys/protosw.h
  head/sys/sys/vimage.h

Modified: head/UPDATING
==============================================================================
--- head/UPDATING	Mon Jun  8 17:11:47 2009	(r193730)
+++ head/UPDATING	Mon Jun  8 17:15:40 2009	(r193731)
@@ -22,6 +22,11 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 8.
 	to maximize performance.  (To disable malloc debugging, run
 	ln -s aj /etc/malloc.conf.)
 
+20090608:
+	The layout of structs ifnet, domain, protosw and vnet_net has
+	changed.  Kernel modules need to be rebuilt.
+	Bump __FreeBSD_version to 800097.
+
 20090602:
 	window(1) has been removed from the base system. It can now be
 	installed from ports. The port is called misc/window.

Modified: head/sys/kern/kern_vimage.c
==============================================================================
--- head/sys/kern/kern_vimage.c	Mon Jun  8 17:11:47 2009	(r193730)
+++ head/sys/kern/kern_vimage.c	Mon Jun  8 17:15:40 2009	(r193731)
@@ -65,8 +65,8 @@ static int vnet_mod_constructor(struct v
 static int vnet_mod_destructor(struct vnet_modlink *);
 
 #ifdef VIMAGE
-static struct vimage *vimage_by_name(struct vimage *, char *);
 static struct vimage *vi_alloc(struct vimage *, char *);
+static int vi_destroy(struct vimage *);
 static struct vimage *vimage_get_next(struct vimage *, struct vimage *, int);
 static void vimage_relative_name(struct vimage *, struct vimage *,
     char *, int);
@@ -122,7 +122,7 @@ vi_if_move(struct vi_req *vi_req, struct
 	struct vnet *new_vnet = NULL;
 
 	/* Check for API / ABI version mismatch. */
-	if (vi_req->vi_api_cookie != VI_API_COOKIE)
+	if (vi_req != NULL && vi_req->vi_api_cookie != VI_API_COOKIE)
 		return (EDOOFUS);
 
 	/* Find the target vnet. */
@@ -216,11 +216,7 @@ vi_td_ioctl(u_long cmd, struct vi_req *v
 
 	case SIOCSPVIMAGE:
 		if (vi_req->vi_req_action == VI_DESTROY) {
-#ifdef NOTYET
 			error = vi_destroy(vip_r);
-#else
-			error = EOPNOTSUPP;
-#endif
 			break;
 		}
 
@@ -283,7 +279,7 @@ vi_child_of(struct vimage *parent, struc
 	return (0);
 }
 
-static struct vimage *
+struct vimage *
 vimage_by_name(struct vimage *top, char *name)
 {
 	struct vimage *vip;
@@ -541,7 +537,6 @@ vnet_mod_constructor(struct vnet_modlink
 	return (0);
 }
 
-
 static int
 vnet_mod_destructor(struct vnet_modlink *vml)
 {
@@ -663,6 +658,68 @@ vi_alloc(struct vimage *parent, char *na
 
 	return (vip);
 }
+
+/*
+ * Destroy a vnet - unlink all linked lists, hashtables etc., free all
+ * the memory, stop all the timers...
+ */
+static int
+vi_destroy(struct vimage *vip)
+{
+	struct vnet *vnet = vip->v_net;
+	struct vprocg *vprocg = vip->v_procg;
+	struct ifnet *ifp, *nifp;
+	struct vnet_modlink *vml;
+
+	/* XXX Beware of races -> more locking to be done... */
+	if (!LIST_EMPTY(&vip->vi_child_head))
+		return (EBUSY);
+
+	if (vprocg->nprocs != 0)
+		return (EBUSY);
+
+	if (vnet->sockcnt != 0)
+		return (EBUSY);
+
+#ifdef INVARIANTS
+	if (vip->vi_ucredrefc != 0)
+		printf("vi_destroy: %s ucredrefc %d\n",
+		    vip->vi_name, vip->vi_ucredrefc);
+#endif
+
+	/* Point with no return - cleanup MUST succeed! */
+	LIST_REMOVE(vip, vi_le);
+	LIST_REMOVE(vip, vi_sibling);
+	LIST_REMOVE(vprocg, vprocg_le);
+
+	VNET_LIST_WLOCK();
+	LIST_REMOVE(vnet, vnet_le);
+	VNET_LIST_WUNLOCK();
+
+	CURVNET_SET_QUIET(vnet);
+	INIT_VNET_NET(vnet);
+
+	/* Return all inherited interfaces to their parent vnets. */
+	TAILQ_FOREACH_SAFE(ifp, &V_ifnet, if_link, nifp) {
+		if (ifp->if_home_vnet != ifp->if_vnet)
+			vi_if_move(NULL, ifp, vip);
+	}
+
+	/* Detach / free per-module state instances. */
+	TAILQ_FOREACH_REVERSE(vml, &vnet_modlink_head,
+			      vnet_modlink_head, vml_mod_le)
+		vnet_mod_destructor(vml);
+
+	CURVNET_RESTORE();
+
+	/* Hopefully, we are OK to free the vnet container itself. */
+	vnet->vnet_magic_n = 0xdeadbeef;
+	free(vnet, M_VNET);
+	free(vprocg, M_VPROCG);
+	free(vip, M_VIMAGE);
+
+	return (0);
+}
 #endif /* VIMAGE */
 
 static void

Modified: head/sys/kern/uipc_domain.c
==============================================================================
--- head/sys/kern/uipc_domain.c	Mon Jun  8 17:11:47 2009	(r193730)
+++ head/sys/kern/uipc_domain.c	Mon Jun  8 17:15:40 2009	(r193731)
@@ -66,6 +66,9 @@ SYSINIT(domainfin, SI_SUB_PROTO_IFATTACH
     NULL);
 
 static vnet_attach_fn net_init_domain;
+#ifdef VIMAGE
+static vnet_detach_fn net_detach_domain;
+#endif
 
 static struct callout pffast_callout;
 static struct callout pfslow_callout;
@@ -107,7 +110,10 @@ struct pr_usrreqs nousrreqs = {
 vnet_modinfo_t vnet_domain_modinfo = {
 	.vmi_id		= VNET_MOD_DOMAIN,
 	.vmi_name	= "domain",
-	.vmi_iattach	= net_init_domain
+	.vmi_iattach	= net_init_domain,
+#ifdef VIMAGE
+	.vmi_idetach	= net_detach_domain,
+#endif
 };
 #endif
 
@@ -190,6 +196,26 @@ net_init_domain(const void *arg)
 	return (0);
 }
 
+#ifdef VIMAGE
+/*
+ * Detach / free a domain instance.
+ */
+static int
+net_detach_domain(const void *arg)
+{
+	const struct domain *dp = arg;
+	struct protosw *pr;
+
+	for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
+		if (pr->pr_destroy)
+			(*pr->pr_destroy)();
+	if (dp->dom_destroy)
+		(*dp->dom_destroy)();
+
+	return (0);
+}
+#endif
+
 /*
  * Add a new protocol domain to the list of supported domains
  * Note: you cant unload it again because a socket may be using it.

Modified: head/sys/net/if.c
==============================================================================
--- head/sys/net/if.c	Mon Jun  8 17:11:47 2009	(r193730)
+++ head/sys/net/if.c	Mon Jun  8 17:15:40 2009	(r193731)
@@ -153,6 +153,9 @@ extern void	nd6_setmtu(struct ifnet *);
 #endif
 
 static int	vnet_net_iattach(const void *);
+#ifdef VIMAGE
+static int	vnet_net_idetach(const void *);
+#endif
 
 #ifdef VIMAGE_GLOBALS
 struct	ifnethead ifnet;	/* depend on static init XXX */
@@ -189,7 +192,10 @@ static const vnet_modinfo_t vnet_net_mod
 	.vmi_name	= "net",
 	.vmi_size	= sizeof(struct vnet_net),
 	.vmi_symmap	= vnet_net_symmap,
-	.vmi_iattach	= vnet_net_iattach
+	.vmi_iattach	= vnet_net_iattach,
+#ifdef VIMAGE
+	.vmi_idetach	= vnet_net_idetach
+#endif
 };
 #endif /* !VIMAGE_GLOBALS */
 
@@ -446,6 +452,22 @@ vnet_net_iattach(const void *unused __un
 	return (0);
 }
 
+#ifdef VIMAGE
+static int
+vnet_net_idetach(const void *unused __unused)
+{
+	INIT_VNET_NET(curvnet);
+
+	VNET_ASSERT(TAILQ_EMPTY(&V_ifnet));
+	VNET_ASSERT(TAILQ_EMPTY(&V_ifg_head));
+	VNET_ASSERT(SLIST_EMPTY(&V_ifklist.kl_list));
+
+	free((caddr_t)V_ifindex_table, M_IFNET);
+
+	return (0);
+}
+#endif
+
 void
 if_grow(void)
 {
@@ -688,6 +710,8 @@ if_attach_internal(struct ifnet *ifp, in
 
 #ifdef VIMAGE
 	ifp->if_vnet = curvnet;
+	if (ifp->if_home_vnet == NULL)
+		ifp->if_home_vnet = curvnet;
 #endif
 
 	if_addgroup(ifp, IFG_ALL);

Modified: head/sys/net/if_gif.c
==============================================================================
--- head/sys/net/if_gif.c	Mon Jun  8 17:11:47 2009	(r193730)
+++ head/sys/net/if_gif.c	Mon Jun  8 17:15:40 2009	(r193731)
@@ -303,12 +303,10 @@ gifmodevent(mod, type, data)
 		break;
 	case MOD_UNLOAD:
 		if_clone_detach(&gif_cloner);
-		mtx_destroy(&gif_mtx);
-#ifdef INET6
-#ifndef VIMAGE
-		V_ip6_gif_hlim = 0;	/* XXX -> vnet_gif_idetach() */
-#endif
+#ifdef VIMAGE
+		vnet_mod_deregister(&vnet_gif_modinfo);
 #endif
+		mtx_destroy(&gif_mtx);
 		break;
 	default:
 		return EOPNOTSUPP;

Modified: head/sys/net/if_loop.c
==============================================================================
--- head/sys/net/if_loop.c	Mon Jun  8 17:11:47 2009	(r193730)
+++ head/sys/net/if_loop.c	Mon Jun  8 17:15:40 2009	(r193731)
@@ -105,6 +105,9 @@ int		looutput(struct ifnet *ifp, struct 
 static int	lo_clone_create(struct if_clone *, int, caddr_t);
 static void	lo_clone_destroy(struct ifnet *);
 static int	vnet_loif_iattach(const void *);
+#ifdef VIMAGE
+static int	vnet_loif_idetach(const void *);
+#endif
 
 #ifdef VIMAGE_GLOBALS
 struct ifnet *loif;			/* Used externally */
@@ -119,7 +122,10 @@ static const vnet_modinfo_t vnet_loif_mo
 	.vmi_id		= VNET_MOD_LOIF,
 	.vmi_dependson	= VNET_MOD_IF_CLONE,
 	.vmi_name	= "loif",
-	.vmi_iattach	= vnet_loif_iattach
+	.vmi_iattach	= vnet_loif_iattach,
+#ifdef VIMAGE
+	.vmi_idetach	= vnet_loif_idetach
+#endif
 };
 #endif /* !VIMAGE_GLOBALS */
 
@@ -128,12 +134,11 @@ IFC_SIMPLE_DECLARE(lo, 1);
 static void
 lo_clone_destroy(struct ifnet *ifp)
 {
-#ifdef INVARIANTS
-	INIT_VNET_NET(ifp->if_vnet);
-#endif
 
+#ifndef VIMAGE
 	/* XXX: destroying lo0 will lead to panics. */
 	KASSERT(V_loif != ifp, ("%s: destroying lo0", __func__));
+#endif
 
 	bpfdetach(ifp);
 	if_detach(ifp);
@@ -166,7 +171,8 @@ lo_clone_create(struct if_clone *ifc, in
 	return (0);
 }
 
-static int vnet_loif_iattach(const void *unused __unused)
+static int
+vnet_loif_iattach(const void *unused __unused)
 {
 	INIT_VNET_NET(curvnet);
 
@@ -175,7 +181,11 @@ static int vnet_loif_iattach(const void 
 #ifdef VIMAGE
 	V_lo_cloner = malloc(sizeof(*V_lo_cloner), M_LO_CLONER,
 	    M_WAITOK | M_ZERO);
+	V_lo_cloner_data = malloc(sizeof(*V_lo_cloner_data), M_LO_CLONER,
+	    M_WAITOK | M_ZERO);
 	bcopy(&lo_cloner, V_lo_cloner, sizeof(*V_lo_cloner));
+	bcopy(lo_cloner.ifc_data, V_lo_cloner_data, sizeof(*V_lo_cloner_data));
+	V_lo_cloner->ifc_data = V_lo_cloner_data;
 	if_clone_attach(V_lo_cloner);
 #else
 	if_clone_attach(&lo_cloner);
@@ -183,6 +193,21 @@ static int vnet_loif_iattach(const void 
 	return (0);
 }
 
+#ifdef VIMAGE
+static int
+vnet_loif_idetach(const void *unused __unused)
+{
+	INIT_VNET_NET(curvnet);
+
+	if_clone_detach(V_lo_cloner);
+	free(V_lo_cloner, M_LO_CLONER);
+	free(V_lo_cloner_data, M_LO_CLONER);
+	V_loif = NULL;
+
+	return (0);
+}
+#endif
+
 static int
 loop_modevent(module_t mod, int type, void *data)
 {

Modified: head/sys/net/if_var.h
==============================================================================
--- head/sys/net/if_var.h	Mon Jun  8 17:11:47 2009	(r193730)
+++ head/sys/net/if_var.h	Mon Jun  8 17:15:40 2009	(r193731)
@@ -71,6 +71,7 @@ struct	ether_header;
 struct	carp_if;
 struct  ifvlantrunk;
 struct	route;
+struct	vnet;
 #endif
 
 #include <sys/queue.h>		/* get TAILQ macros */
@@ -169,6 +170,9 @@ struct ifnet {
 		(struct ifnet *);
 	int	(*if_transmit)		/* initiate output routine */
 		(struct ifnet *, struct mbuf *);
+	void	(*if_reassign)		/* reassign to vnet routine */
+		(struct ifnet *, struct vnet *, char *);
+	struct	vnet *if_home_vnet;	/* where this ifnet originates from */
 	struct	ifaddr	*if_addr;	/* pointer to link-level address */
 	void	*if_llsoftc;		/* link layer softc */
 	int	if_drv_flags;		/* driver-managed status flags */

Modified: head/sys/net/route.c
==============================================================================
--- head/sys/net/route.c	Mon Jun  8 17:11:47 2009	(r193730)
+++ head/sys/net/route.c	Mon Jun  8 17:15:40 2009	(r193731)
@@ -99,12 +99,18 @@ static int	rttrash;		/* routes not in ta
 static void rt_maskedcopy(struct sockaddr *,
 	    struct sockaddr *, struct sockaddr *);
 static int vnet_route_iattach(const void *);
+#ifdef VIMAGE
+static int vnet_route_idetach(const void *);
+#endif
 
 #ifndef VIMAGE_GLOBALS
 static const vnet_modinfo_t vnet_rtable_modinfo = {
 	.vmi_id		= VNET_MOD_RTABLE,
 	.vmi_name	= "rtable",
-	.vmi_iattach	= vnet_route_iattach
+	.vmi_iattach	= vnet_route_iattach,
+#ifdef VIMAGE
+	.vmi_idetach	= vnet_route_idetach
+#endif
 };
 #endif /* !VIMAGE_GLOBALS */
 
@@ -194,7 +200,8 @@ route_init(void)
 #endif
 }
 
-static int vnet_route_iattach(const void *unused __unused)
+static int
+vnet_route_iattach(const void *unused __unused)
 {
 	INIT_VNET_NET(curvnet);
 	struct domain *dom;
@@ -235,6 +242,36 @@ static int vnet_route_iattach(const void
 	return (0);
 }
 
+#ifdef VIMAGE
+static int
+vnet_route_idetach(const void *unused __unused)
+{
+	int table;
+	int fam;
+	struct domain *dom;
+	struct radix_node_head **rnh;
+
+	for (dom = domains; dom; dom = dom->dom_next) {
+		if (dom->dom_rtdetach) {
+			for (table = 0; table < rt_numfibs; table++) {
+				if ( (fam = dom->dom_family) == AF_INET ||
+				    table == 0) {
+					/* For now only AF_INET has > 1 tbl. */
+					rnh = rt_tables_get_rnh_ptr(table, fam);
+					if (rnh == NULL)
+						panic("%s: rnh NULL", __func__);
+					dom->dom_rtdetach((void **)rnh,
+					    dom->dom_rtoffset);
+				} else {
+					break;
+				}
+			}
+		}
+	}
+	return (0);
+}
+#endif
+
 #ifndef _SYS_SYSPROTO_H_
 struct setfib_args {
 	int     fibnum;

Modified: head/sys/net/vnet.h
==============================================================================
--- head/sys/net/vnet.h	Mon Jun  8 17:11:47 2009	(r193730)
+++ head/sys/net/vnet.h	Mon Jun  8 17:15:40 2009	(r193731)
@@ -51,6 +51,7 @@ struct vnet_net {
 
 	struct ifnet *		_loif;
 	struct if_clone *	_lo_cloner;
+	struct ifc_simple_data *_lo_cloner_data;
 
 	LIST_HEAD(, rawcb)	_rawcb_list;
 
@@ -87,6 +88,7 @@ extern struct vnet_net vnet_net_0;
 #define	V_ifklist		VNET_NET(ifklist)
 #define	V_ifnet			VNET_NET(ifnet)
 #define	V_lo_cloner		VNET_NET(lo_cloner)
+#define	V_lo_cloner_data	VNET_NET(lo_cloner_data)
 #define	V_loif			VNET_NET(loif)
 #define	V_rawcb_list		VNET_NET(rawcb_list)
 #define	V_rt_tables		VNET_NET(rt_tables)

Modified: head/sys/netgraph/ng_base.c
==============================================================================
--- head/sys/netgraph/ng_base.c	Mon Jun  8 17:11:47 2009	(r193730)
+++ head/sys/netgraph/ng_base.c	Mon Jun  8 17:15:40 2009	(r193731)
@@ -85,6 +85,9 @@ struct vnet_netgraph vnet_netgraph_0;
 static struct mtx	ng_topo_mtx;
 
 static vnet_attach_fn vnet_netgraph_iattach;
+#ifdef VIMAGE
+static vnet_detach_fn vnet_netgraph_idetach;
+#endif
 
 #ifdef	NETGRAPH_DEBUG
 static struct mtx	ng_nodelist_mtx; /* protects global node/hook lists */
@@ -647,6 +650,9 @@ ng_make_node_common(struct ng_type *type
 		return (ENOMEM);
 	}
 	node->nd_type = type;
+#ifdef VIMAGE
+	node->nd_vnet = curvnet;
+#endif
 	NG_NODE_REF(node);				/* note reference */
 	type->refs++;
 
@@ -3074,15 +3080,17 @@ ng_mod_event(module_t mod, int event, vo
 static const vnet_modinfo_t vnet_netgraph_modinfo = {
 	.vmi_id		= VNET_MOD_NETGRAPH,
 	.vmi_name	= "netgraph",
-#ifdef VIMAGE
 	.vmi_size	= sizeof(struct vnet_netgraph),
+	.vmi_dependson	= VNET_MOD_LOIF,
+	.vmi_iattach	= vnet_netgraph_iattach,
+#ifdef VIMAGE
+	.vmi_idetach	= vnet_netgraph_idetach
 #endif
-	.vmi_iattach	= vnet_netgraph_iattach
 };
 #endif
 
 static int
-vnet_netgraph_iattach(const void *arg __unused)
+vnet_netgraph_iattach(const void *unused __unused)
 {
 	INIT_VNET_NETGRAPH(curvnet);
 
@@ -3091,6 +3099,33 @@ vnet_netgraph_iattach(const void *arg __
 	return (0);
 }
 
+#ifdef VIMAGE 
+static int
+vnet_netgraph_idetach(const void *unused __unused)
+{
+	INIT_VNET_NETGRAPH(curvnet);
+	node_p node, last_killed = NULL;
+
+	while ((node = LIST_FIRST(&V_ng_nodelist)) != NULL) {
+		if (node == last_killed) {
+			/* This should never happen */
+			node->nd_flags |= NGF_REALLY_DIE;
+			printf("netgraph node %s needs NGF_REALLY_DIE\n",
+			    node->nd_name);
+			ng_rmnode(node, NULL, NULL, 0);
+			/* This must never happen */
+			if (node == LIST_FIRST(&V_ng_nodelist))
+				panic("netgraph node %s won't die",
+				    node->nd_name);
+		}
+		ng_rmnode(node, NULL, NULL, 0);
+		last_killed = node;
+	}
+
+	return (0);
+}
+#endif /* VIMAGE */
+
 /*
  * Handle loading and unloading for this code.
  * The only thing we need to link into is the NETISR strucure.
@@ -3313,6 +3348,7 @@ ngthread(void *arg)
 			NG_WORKLIST_SLEEP();
 		STAILQ_REMOVE_HEAD(&ng_worklist, nd_input_queue.q_work);
 		NG_WORKLIST_UNLOCK();
+		CURVNET_SET(node->nd_vnet);
 		CTR3(KTR_NET, "%20s: node [%x] (%p) taken off worklist",
 		    __func__, node->nd_ID, node);
 		/*
@@ -3342,6 +3378,7 @@ ngthread(void *arg)
 			}
 		}
 		NG_NODE_UNREF(node);
+		CURVNET_RESTORE();
 	}
 }
 
@@ -3675,7 +3712,9 @@ ng_callout_trampoline(void *arg)
 {
 	item_p item = arg;
 
+	CURVNET_SET(NGI_NODE(item)->nd_vnet);
 	ng_snd_item(item, 0);
+	CURVNET_RESTORE();
 }
 
 

Modified: head/sys/netinet/in_proto.c
==============================================================================
--- head/sys/netinet/in_proto.c	Mon Jun  8 17:11:47 2009	(r193730)
+++ head/sys/netinet/in_proto.c	Mon Jun  8 17:15:40 2009	(r193731)
@@ -127,6 +127,9 @@ struct protosw inetsw[] = {
 	.pr_ctlinput =		udp_ctlinput,
 	.pr_ctloutput =		ip_ctloutput,
 	.pr_init =		udp_init,
+#ifdef VIMAGE
+	.pr_destroy =		udp_destroy,
+#endif
 	.pr_usrreqs =		&udp_usrreqs
 },
 {
@@ -138,6 +141,9 @@ struct protosw inetsw[] = {
 	.pr_ctlinput =		tcp_ctlinput,
 	.pr_ctloutput =		tcp_ctloutput,
 	.pr_init =		tcp_init,
+#ifdef VIMAGE
+	.pr_destroy =		tcp_destroy,
+#endif
 	.pr_slowtimo =		tcp_slowtimo,
 	.pr_drain =		tcp_drain,
 	.pr_usrreqs =		&tcp_usrreqs
@@ -348,11 +354,15 @@ IPPROTOSPACER,
 	.pr_input =		rip_input,
 	.pr_ctloutput =		rip_ctloutput,
 	.pr_init =		rip_init,
+#ifdef VIMAGE
+	.pr_destroy =		rip_destroy,
+#endif
 	.pr_usrreqs =		&rip_usrreqs
 },
 };
 
 extern int in_inithead(void **, int);
+extern int in_detachhead(void **, int);
 
 struct domain inetdomain = {
 	.dom_family =		AF_INET,
@@ -364,6 +374,9 @@ struct domain inetdomain = {
 #else
 	.dom_rtattach =		in_inithead,
 #endif
+#ifdef VIMAGE
+	.dom_rtdetach =		in_detachhead,
+#endif
 	.dom_rtoffset =		32,
 	.dom_maxrtkey =		sizeof(struct sockaddr_in),
 	.dom_ifattach =		in_domifattach,

Modified: head/sys/netinet/in_rmx.c
==============================================================================
--- head/sys/netinet/in_rmx.c	Mon Jun  8 17:11:47 2009	(r193730)
+++ head/sys/netinet/in_rmx.c	Mon Jun  8 17:15:40 2009	(r193731)
@@ -65,6 +65,9 @@ __FBSDID("$FreeBSD$");
 #include <netinet/vinet.h>
 
 extern int	in_inithead(void **head, int off);
+#ifdef VIMAGE
+extern int	in_detachhead(void **head, int off);
+#endif
 
 #define RTPRF_OURS		RTF_PROTO3	/* set on routes we manage */
 
@@ -382,6 +385,17 @@ in_inithead(void **head, int off)
 	return 1;
 }
 
+#ifdef VIMAGE
+int
+in_detachhead(void **head, int off)
+{
+	INIT_VNET_INET(curvnet);
+
+	callout_drain(&V_rtq_timer);
+	return (1);
+}
+#endif
+
 /*
  * This zaps old routes when the interface goes down or interface
  * address is deleted.  In the latter case, it deletes static routes

Modified: head/sys/netinet/ip_var.h
==============================================================================
--- head/sys/netinet/ip_var.h	Mon Jun  8 17:11:47 2009	(r193730)
+++ head/sys/netinet/ip_var.h	Mon Jun  8 17:15:40 2009	(r193731)
@@ -210,6 +210,9 @@ u_int16_t	ip_randomid(void);
 int	rip_ctloutput(struct socket *, struct sockopt *);
 void	rip_ctlinput(int, struct sockaddr *, void *);
 void	rip_init(void);
+#ifdef VIMAGE
+void	rip_destroy(void);
+#endif
 void	rip_input(struct mbuf *, int);
 int	rip_output(struct mbuf *, struct socket *, u_long);
 void	ipip_input(struct mbuf *, int);

Modified: head/sys/netinet/raw_ip.c
==============================================================================
--- head/sys/netinet/raw_ip.c	Mon Jun  8 17:11:47 2009	(r193730)
+++ head/sys/netinet/raw_ip.c	Mon Jun  8 17:15:40 2009	(r193731)
@@ -205,6 +205,19 @@ rip_init(void)
 	    EVENTHANDLER_PRI_ANY);
 }
 
+#ifdef VIMAGE
+void
+rip_destroy(void)
+{
+	INIT_VNET_INET(curvnet);
+
+	hashdestroy(V_ripcbinfo.ipi_hashbase, M_PCB,
+	    V_ripcbinfo.ipi_hashmask);
+	hashdestroy(V_ripcbinfo.ipi_porthashbase, M_PCB,
+	    V_ripcbinfo.ipi_porthashmask);
+}
+#endif
+
 static int
 rip_append(struct inpcb *last, struct ip *ip, struct mbuf *n,
     struct sockaddr_in *ripsrc)

Modified: head/sys/netinet/tcp_hostcache.c
==============================================================================
--- head/sys/netinet/tcp_hostcache.c	Mon Jun  8 17:11:47 2009	(r193730)
+++ head/sys/netinet/tcp_hostcache.c	Mon Jun  8 17:15:40 2009	(r193731)
@@ -230,6 +230,18 @@ tcp_hc_init(void)
 	    tcp_hc_purge, curvnet);
 }
 
+#ifdef VIMAGE
+void
+tcp_hc_destroy(void)
+{
+	INIT_VNET_INET(curvnet);
+
+	/* XXX TODO walk the hashtable and free all entries  */
+
+	callout_drain(&V_tcp_hc_callout);
+}
+#endif
+
 /*
  * Internal function: look up an entry in the hostcache or return NULL.
  *

Modified: head/sys/netinet/tcp_subr.c
==============================================================================
--- head/sys/netinet/tcp_subr.c	Mon Jun  8 17:11:47 2009	(r193730)
+++ head/sys/netinet/tcp_subr.c	Mon Jun  8 17:15:40 2009	(r193731)
@@ -426,6 +426,25 @@ tcp_init(void)
 		EVENTHANDLER_PRI_ANY);
 }
 
+#ifdef VIMAGE
+void
+tcp_destroy(void)
+{
+	INIT_VNET_INET(curvnet);
+
+	tcp_tw_destroy();
+	tcp_hc_destroy();
+	syncache_destroy();
+
+	/* XXX check that hashes are empty! */
+	hashdestroy(V_tcbinfo.ipi_hashbase, M_PCB,
+	    V_tcbinfo.ipi_hashmask);
+	hashdestroy(V_tcbinfo.ipi_porthashbase, M_PCB,
+	    V_tcbinfo.ipi_porthashmask);
+	INP_INFO_LOCK_DESTROY(&V_tcbinfo);
+}
+#endif
+
 void
 tcp_fini(void *xtp)
 {

Modified: head/sys/netinet/tcp_syncache.c
==============================================================================
--- head/sys/netinet/tcp_syncache.c	Mon Jun  8 17:11:47 2009	(r193730)
+++ head/sys/netinet/tcp_syncache.c	Mon Jun  8 17:15:40 2009	(r193731)
@@ -275,6 +275,19 @@ syncache_init(void)
 	uma_zone_set_max(V_tcp_syncache.zone, V_tcp_syncache.cache_limit);
 }
 
+#ifdef VIMAGE
+void
+syncache_destroy(void)
+{
+	INIT_VNET_INET(curvnet);
+
+	/* XXX walk the cache, free remaining objects, stop timers */
+
+	uma_zdestroy(V_tcp_syncache.zone);
+	FREE(V_tcp_syncache.hashbase, M_SYNCACHE);
+}
+#endif
+
 /*
  * Inserts a syncache entry into the specified bucket row.
  * Locks and unlocks the syncache_head autonomously.

Modified: head/sys/netinet/tcp_syncache.h
==============================================================================
--- head/sys/netinet/tcp_syncache.h	Mon Jun  8 17:11:47 2009	(r193730)
+++ head/sys/netinet/tcp_syncache.h	Mon Jun  8 17:15:40 2009	(r193731)
@@ -35,6 +35,9 @@
 #ifdef _KERNEL
 
 void	 syncache_init(void);
+#ifdef VIMAGE
+void	syncache_destroy(void);
+#endif
 void	 syncache_unreach(struct in_conninfo *, struct tcphdr *);
 int	 syncache_expand(struct in_conninfo *, struct tcpopt *,
 	     struct tcphdr *, struct socket **, struct mbuf *);

Modified: head/sys/netinet/tcp_timewait.c
==============================================================================
--- head/sys/netinet/tcp_timewait.c	Mon Jun  8 17:11:47 2009	(r193730)
+++ head/sys/netinet/tcp_timewait.c	Mon Jun  8 17:15:40 2009	(r193731)
@@ -179,6 +179,20 @@ tcp_tw_init(void)
 	TAILQ_INIT(&V_twq_2msl);
 }
 
+#ifdef VIMAGE
+void
+tcp_tw_destroy(void)
+{
+	INIT_VNET_INET(curvnet);
+	struct tcptw *tw;
+
+	INP_INFO_WLOCK(&V_tcbinfo);
+	while((tw = TAILQ_FIRST(&V_twq_2msl)) != NULL)
+		tcp_twclose(tw, 0);
+	INP_INFO_WUNLOCK(&V_tcbinfo);
+}
+#endif
+
 /*
  * Move a TCP connection into TIME_WAIT state.
  *    tcbinfo is locked.

Modified: head/sys/netinet/tcp_var.h
==============================================================================
--- head/sys/netinet/tcp_var.h	Mon Jun  8 17:11:47 2009	(r193730)
+++ head/sys/netinet/tcp_var.h	Mon Jun  8 17:15:40 2009	(r193731)
@@ -584,6 +584,9 @@ struct tcpcb *
 void	 tcp_drain(void);
 void	 tcp_fasttimo(void);
 void	 tcp_init(void);
+#ifdef VIMAGE
+void	 tcp_destroy(void);
+#endif
 void	 tcp_fini(void *);
 char 	*tcp_log_addrs(struct in_conninfo *, struct tcphdr *, void *,
 	    const void *);
@@ -605,6 +608,9 @@ int	 tcp_output(struct tcpcb *);
 void	 tcp_respond(struct tcpcb *, void *,
 	    struct tcphdr *, struct mbuf *, tcp_seq, tcp_seq, int);
 void	 tcp_tw_init(void);
+#ifdef VIMAGE
+void	 tcp_tw_destroy(void);
+#endif
 void	 tcp_tw_zone_change(void);
 int	 tcp_twcheck(struct inpcb *, struct tcpopt *, struct tcphdr *,
 	    struct mbuf *, int);
@@ -625,6 +631,9 @@ void	 tcp_xmit_bandwidth_limit(struct tc
  * All tcp_hc_* functions are IPv4 and IPv6 (via in_conninfo)
  */
 void	 tcp_hc_init(void);
+#ifdef VIMAGE
+void	 tcp_hc_destroy(void);
+#endif
 void	 tcp_hc_get(struct in_conninfo *, struct hc_metrics_lite *);
 u_long	 tcp_hc_getmtu(struct in_conninfo *);
 void	 tcp_hc_updatemtu(struct in_conninfo *, u_long);

Modified: head/sys/netinet/udp_usrreq.c
==============================================================================
--- head/sys/netinet/udp_usrreq.c	Mon Jun  8 17:11:47 2009	(r193730)
+++ head/sys/netinet/udp_usrreq.c	Mon Jun  8 17:15:40 2009	(r193731)
@@ -221,6 +221,20 @@ udp_discardcb(struct udpcb *up)
 	uma_zfree(V_udpcb_zone, up);
 }
 
+#ifdef VIMAGE
+void
+udp_destroy(void)
+{
+	INIT_VNET_INET(curvnet);
+
+	hashdestroy(V_udbinfo.ipi_hashbase, M_PCB,
+	    V_udbinfo.ipi_hashmask);
+	hashdestroy(V_udbinfo.ipi_porthashbase, M_PCB,
+	    V_udbinfo.ipi_porthashmask);
+	INP_INFO_LOCK_DESTROY(&V_udbinfo);
+}
+#endif
+
 /*
  * Subroutine of udp_input(), which appends the provided mbuf chain to the
  * passed pcb/socket.  The caller must provide a sockaddr_in via udp_in that

Modified: head/sys/netinet/udp_var.h
==============================================================================
--- head/sys/netinet/udp_var.h	Mon Jun  8 17:11:47 2009	(r193730)
+++ head/sys/netinet/udp_var.h	Mon Jun  8 17:15:40 2009	(r193731)
@@ -128,6 +128,9 @@ void		 udp_discardcb(struct udpcb *);
 
 void		 udp_ctlinput(int, struct sockaddr *, void *);
 void		 udp_init(void);
+#ifdef VIMAGE
+void		 udp_destroy(void);
+#endif
 void		 udp_input(struct mbuf *, int);
 struct inpcb	*udp_notify(struct inpcb *inp, int errno);
 int		 udp_shutdown(struct socket *so);

Modified: head/sys/netinet6/in6_proto.c
==============================================================================
--- head/sys/netinet6/in6_proto.c	Mon Jun  8 17:11:47 2009	(r193730)
+++ head/sys/netinet6/in6_proto.c	Mon Jun  8 17:15:40 2009	(r193731)
@@ -148,6 +148,9 @@ struct ip6protosw inet6sw[] = {
 	.pr_domain =		&inet6domain,
 	.pr_protocol =		IPPROTO_IPV6,
 	.pr_init =		ip6_init,
+#ifdef VIMAGE
+	.pr_destroy =		ip6_destroy,
+#endif
 	.pr_slowtimo =		frag6_slowtimo,
 	.pr_drain =		frag6_drain,
 	.pr_usrreqs =		&nousrreqs,
@@ -349,6 +352,9 @@ struct ip6protosw inet6sw[] = {
 };
 
 extern int in6_inithead(void **, int);
+#ifdef VIMAGE
+extern int in6_detachhead(void **, int);
+#endif
 
 struct domain inet6domain = {
 	.dom_family =		AF_INET6,
@@ -361,6 +367,9 @@ struct domain inet6domain = {
 #else
 	.dom_rtattach =		in6_inithead,
 #endif
+#ifdef VIMAGE
+	.dom_rtdetach =		in6_detachhead,
+#endif
 	.dom_rtoffset =		offsetof(struct sockaddr_in6, sin6_addr) << 3,
 	.dom_maxrtkey =		sizeof(struct sockaddr_in6),
 	.dom_ifattach =		in6_domifattach,

Modified: head/sys/netinet6/in6_rmx.c
==============================================================================
--- head/sys/netinet6/in6_rmx.c	Mon Jun  8 17:11:47 2009	(r193730)
+++ head/sys/netinet6/in6_rmx.c	Mon Jun  8 17:15:40 2009	(r193731)
@@ -112,6 +112,9 @@ __FBSDID("$FreeBSD$");
 #include <netinet/tcp_var.h>
 
 extern int	in6_inithead(void **head, int off);
+#ifdef VIMAGE
+extern int	in6_detachhead(void **head, int off);
+#endif
 
 #define RTPRF_OURS		RTF_PROTO3	/* set on routes we manage */
 
@@ -464,3 +467,15 @@ in6_inithead(void **head, int off)
 	in6_mtutimo(curvnet);	/* kick off timeout first time */
 	return 1;
 }
+
+#ifdef VIMAGE
+int
+in6_detachhead(void **head, int off)
+{
+	INIT_VNET_INET6(curvnet);
+
+	callout_drain(&V_rtq_timer6);
+	callout_drain(&V_rtq_mtutimer);
+	return (1);
+}
+#endif

Modified: head/sys/netinet6/ip6_input.c
==============================================================================
--- head/sys/netinet6/ip6_input.c	Mon Jun  8 17:11:47 2009	(r193730)
+++ head/sys/netinet6/ip6_input.c	Mon Jun  8 17:15:40 2009	(r193731)
@@ -303,6 +303,17 @@ ip6_init(void)
 	netisr_register(&ip6_nh);
 }
 
+#ifdef VIMAGE
+void
+ip6_destroy()
+{
+	INIT_VNET_INET6(curvnet);
+
+	nd6_destroy();
+	callout_drain(&V_in6_tmpaddrtimer_ch);
+}
+#endif
+
 static int
 ip6_init2_vnet(const void *unused __unused)
 {

Modified: head/sys/netinet6/ip6_var.h
==============================================================================
--- head/sys/netinet6/ip6_var.h	Mon Jun  8 17:11:47 2009	(r193730)
+++ head/sys/netinet6/ip6_var.h	Mon Jun  8 17:15:40 2009	(r193731)
@@ -339,6 +339,9 @@ int	icmp6_ctloutput __P((struct socket *
 
 struct in6_ifaddr;
 void	ip6_init __P((void));
+#ifdef VIMAGE
+void	ip6_destroy __P((void));
+#endif
 void	ip6_input __P((struct mbuf *));
 struct in6_ifaddr *ip6_getdstifaddr __P((struct mbuf *));
 void	ip6_freepcbopts __P((struct ip6_pktopts *));

Modified: head/sys/netinet6/ip6protosw.h
==============================================================================
--- head/sys/netinet6/ip6protosw.h	Mon Jun  8 17:11:47 2009	(r193730)
+++ head/sys/netinet6/ip6protosw.h	Mon Jun  8 17:15:40 2009	(r193731)
@@ -129,6 +129,8 @@ struct ip6protosw {
 /* utility hooks */
 	void	(*pr_init)		/* initialization hook */
 			__P((void));
+	void	(*pr_destroy)		/* cleanup hook */
+			__P((void));
 
 	void	(*pr_fasttimo)		/* fast timeout (200ms) */
 			__P((void));

Modified: head/sys/netinet6/nd6.c
==============================================================================
--- head/sys/netinet6/nd6.c	Mon Jun  8 17:11:47 2009	(r193730)
+++ head/sys/netinet6/nd6.c	Mon Jun  8 17:15:40 2009	(r193731)
@@ -134,14 +134,8 @@ void
 nd6_init(void)
 {
 	INIT_VNET_INET6(curvnet);
-	static int nd6_init_done = 0;
 	int i;
 
-	if (nd6_init_done) {
-		log(LOG_NOTICE, "nd6_init called more than once(ignored)\n");
-		return;
-	}
-
 	V_nd6_prune	= 1;	/* walk list every 1 seconds */
 	V_nd6_delay	= 5;	/* delay first probe time 5 second */
 	V_nd6_umaxtries	= 3;	/* maximum unicast query */
@@ -180,6 +174,8 @@ nd6_init(void)
 	V_ip6_temp_valid_lifetime = DEF_TEMP_VALID_LIFETIME;
 	V_ip6_temp_regen_advance = TEMPADDR_REGEN_ADVANCE;
 
+	V_ip6_desync_factor = 0;
+
 	all1_sa.sin6_family = AF_INET6;
 	all1_sa.sin6_len = sizeof(struct sockaddr_in6);
 	for (i = 0; i < sizeof(all1_sa.sin6_addr); i++)
@@ -191,10 +187,19 @@ nd6_init(void)
 	callout_init(&V_nd6_slowtimo_ch, 0);
 	callout_reset(&V_nd6_slowtimo_ch, ND6_SLOWTIMER_INTERVAL * hz,
 	    nd6_slowtimo, curvnet);
+}
 
-	nd6_init_done = 1;
 
+#ifdef VIMAGE
+void
+nd6_destroy()
+{
+	INIT_VNET_INET6(curvnet);
+
+	callout_drain(&V_nd6_slowtimo_ch);
+	callout_drain(&V_nd6_timer_ch);
 }
+#endif
 
 struct nd_ifinfo *
 nd6_ifattach(struct ifnet *ifp)

Modified: head/sys/netinet6/nd6.h
==============================================================================
--- head/sys/netinet6/nd6.h	Mon Jun  8 17:11:47 2009	(r193730)
+++ head/sys/netinet6/nd6.h	Mon Jun  8 17:15:40 2009	(r193731)
@@ -371,6 +371,9 @@ union nd_opts {
 /* XXX: need nd6_var.h?? */
 /* nd6.c */
 void nd6_init __P((void));
+#ifdef VIMAGE
+void nd6_destroy __P((void));
+#endif
 struct nd_ifinfo *nd6_ifattach __P((struct ifnet *));
 void nd6_ifdetach __P((struct nd_ifinfo *));
 int nd6_is_addr_neighbor __P((struct sockaddr_in6 *, struct ifnet *));

Modified: head/sys/netipsec/ipsec.c
==============================================================================
--- head/sys/netipsec/ipsec.c	Mon Jun  8 17:11:47 2009	(r193730)
+++ head/sys/netipsec/ipsec.c	Mon Jun  8 17:15:40 2009	(r193731)

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-src-all mailing list