PERFORCE change 110833 for review

Marko Zec zec at FreeBSD.org
Fri Dec 1 13:07:04 PST 2006


http://perforce.freebsd.org/chv.cgi?CH=110833

Change 110833 by zec at zec_tca51 on 2006/12/01 21:06:02

	Import a jumbo network stack virtualization patch
	from a private CVS tree.

Affected files ...

.. //depot/projects/vimage/src/sys/conf/files#2 edit
.. //depot/projects/vimage/src/sys/conf/options#2 edit
.. //depot/projects/vimage/src/sys/kern/init_main.c#2 edit
.. //depot/projects/vimage/src/sys/kern/kern_fork.c#2 edit
.. //depot/projects/vimage/src/sys/kern/kern_kse.c#2 edit
.. //depot/projects/vimage/src/sys/kern/kern_linker.c#2 edit
.. //depot/projects/vimage/src/sys/kern/kern_synch.c#2 edit
.. //depot/projects/vimage/src/sys/kern/kern_sysctl.c#2 edit
.. //depot/projects/vimage/src/sys/kern/kern_thr.c#2 edit
.. //depot/projects/vimage/src/sys/kern/kern_uuid.c#2 edit
.. //depot/projects/vimage/src/sys/kern/kern_vimage.c#2 edit
.. //depot/projects/vimage/src/sys/kern/subr_pcpu.c#2 edit
.. //depot/projects/vimage/src/sys/kern/sys_socket.c#2 edit
.. //depot/projects/vimage/src/sys/kern/uipc_socket.c#2 edit
.. //depot/projects/vimage/src/sys/kern/uipc_syscalls.c#2 edit
.. //depot/projects/vimage/src/sys/net/bpf.c#2 edit
.. //depot/projects/vimage/src/sys/net/if.c#2 edit
.. //depot/projects/vimage/src/sys/net/if_clone.c#2 edit
.. //depot/projects/vimage/src/sys/net/if_ethersubr.c#2 edit
.. //depot/projects/vimage/src/sys/net/if_loop.c#2 edit
.. //depot/projects/vimage/src/sys/net/if_mib.c#2 edit
.. //depot/projects/vimage/src/sys/net/if_spppsubr.c#2 edit
.. //depot/projects/vimage/src/sys/net/if_stf.c#2 edit
.. //depot/projects/vimage/src/sys/net/if_tap.c#2 edit
.. //depot/projects/vimage/src/sys/net/if_var.h#2 edit
.. //depot/projects/vimage/src/sys/net/netisr.c#2 edit
.. //depot/projects/vimage/src/sys/net/route.c#2 edit
.. //depot/projects/vimage/src/sys/net/rtsock.c#2 edit
.. //depot/projects/vimage/src/sys/net/vnet.h#2 edit
.. //depot/projects/vimage/src/sys/netgraph/ng_base.c#2 edit
.. //depot/projects/vimage/src/sys/netgraph/ng_ether.c#2 edit
.. //depot/projects/vimage/src/sys/netgraph/vnetgraph.h#2 edit
.. //depot/projects/vimage/src/sys/netinet/icmp_var.h#2 edit
.. //depot/projects/vimage/src/sys/netinet/if_ether.c#2 edit
.. //depot/projects/vimage/src/sys/netinet/igmp.c#2 edit
.. //depot/projects/vimage/src/sys/netinet/in.c#2 edit
.. //depot/projects/vimage/src/sys/netinet/in_pcb.c#2 edit
.. //depot/projects/vimage/src/sys/netinet/in_rmx.c#2 edit
.. //depot/projects/vimage/src/sys/netinet/in_var.h#2 edit
.. //depot/projects/vimage/src/sys/netinet/ip_divert.c#2 edit
.. //depot/projects/vimage/src/sys/netinet/ip_fastfwd.c#2 edit
.. //depot/projects/vimage/src/sys/netinet/ip_fw2.c#2 edit
.. //depot/projects/vimage/src/sys/netinet/ip_icmp.c#2 edit
.. //depot/projects/vimage/src/sys/netinet/ip_input.c#2 edit
.. //depot/projects/vimage/src/sys/netinet/ip_options.c#2 edit
.. //depot/projects/vimage/src/sys/netinet/ip_output.c#2 edit
.. //depot/projects/vimage/src/sys/netinet/ip_var.h#2 edit
.. //depot/projects/vimage/src/sys/netinet/raw_ip.c#2 edit
.. //depot/projects/vimage/src/sys/netinet/tcp_hostcache.c#2 edit
.. //depot/projects/vimage/src/sys/netinet/tcp_input.c#2 edit
.. //depot/projects/vimage/src/sys/netinet/tcp_output.c#2 edit
.. //depot/projects/vimage/src/sys/netinet/tcp_sack.c#2 edit
.. //depot/projects/vimage/src/sys/netinet/tcp_subr.c#2 edit
.. //depot/projects/vimage/src/sys/netinet/tcp_syncache.c#2 edit
.. //depot/projects/vimage/src/sys/netinet/tcp_timer.c#2 edit
.. //depot/projects/vimage/src/sys/netinet/tcp_usrreq.c#2 edit
.. //depot/projects/vimage/src/sys/netinet/tcp_var.h#2 edit
.. //depot/projects/vimage/src/sys/netinet/udp_usrreq.c#2 edit
.. //depot/projects/vimage/src/sys/netinet/udp_var.h#2 edit
.. //depot/projects/vimage/src/sys/netinet/vinet.h#2 edit
.. //depot/projects/vimage/src/sys/netinet6/icmp6.c#2 edit
.. //depot/projects/vimage/src/sys/netinet6/in6.c#2 edit
.. //depot/projects/vimage/src/sys/netinet6/in6_ifattach.c#2 edit
.. //depot/projects/vimage/src/sys/netinet6/in6_pcb.c#2 edit
.. //depot/projects/vimage/src/sys/netinet6/in6_rmx.c#2 edit
.. //depot/projects/vimage/src/sys/netinet6/in6_src.c#2 edit
.. //depot/projects/vimage/src/sys/netinet6/ip6_input.c#2 edit
.. //depot/projects/vimage/src/sys/netinet6/ip6_mroute.c#2 edit
.. //depot/projects/vimage/src/sys/netinet6/ip6_output.c#2 edit
.. //depot/projects/vimage/src/sys/netinet6/mld6.c#2 edit
.. //depot/projects/vimage/src/sys/netinet6/nd6.c#2 edit
.. //depot/projects/vimage/src/sys/netinet6/nd6_nbr.c#2 edit
.. //depot/projects/vimage/src/sys/netinet6/nd6_rtr.c#2 edit
.. //depot/projects/vimage/src/sys/netinet6/raw_ip6.c#2 edit
.. //depot/projects/vimage/src/sys/netinet6/scope6.c#2 edit
.. //depot/projects/vimage/src/sys/netinet6/udp6_output.c#2 edit
.. //depot/projects/vimage/src/sys/netinet6/udp6_usrreq.c#2 edit
.. //depot/projects/vimage/src/sys/netinet6/vinet6.h#2 edit
.. //depot/projects/vimage/src/sys/sys/kernel.h#2 edit
.. //depot/projects/vimage/src/sys/sys/proc.h#2 edit
.. //depot/projects/vimage/src/sys/sys/socketvar.h#2 edit
.. //depot/projects/vimage/src/sys/sys/sockio.h#2 edit
.. //depot/projects/vimage/src/sys/sys/sysctl.h#2 edit
.. //depot/projects/vimage/src/sys/sys/vimage.h#2 edit

Differences ...

==== //depot/projects/vimage/src/sys/conf/files#2 (text+ko) ====

@@ -1374,6 +1374,7 @@
 kern/kern_timeout.c		standard
 kern/kern_umtx.c		standard
 kern/kern_uuid.c		standard
+kern/kern_vimage.c		optional vimage
 kern/kern_xxx.c			standard
 kern/link_elf.c			standard
 kern/linker_if.m		standard

==== //depot/projects/vimage/src/sys/conf/options#2 (text+ko) ====

@@ -755,3 +755,6 @@
 
 # snd_emu10kx sound driver options
 SND_EMU10KX_MULTICHANNEL	opt_emu10kx.h
+
+# Virtualize network stack
+VIMAGE			opt_vimage.h

==== //depot/projects/vimage/src/sys/kern/init_main.c#2 (text+ko) ====

@@ -47,6 +47,7 @@
 #include "opt_ddb.h"
 #include "opt_init_path.h"
 #include "opt_mac.h"
+#include "opt_vimage.h"
 
 #include <sys/param.h>
 #include <sys/kernel.h>
@@ -73,6 +74,7 @@
 #include <sys/unistd.h>
 #include <sys/malloc.h>
 #include <sys/conf.h>
+#include <sys/vimage.h>
 
 #include <machine/cpu.h>
 
@@ -476,6 +478,11 @@
 #endif
 	td->td_ucred = crhold(p->p_ucred);
 
+#ifdef VIMAGE
+        /* Init lives in the default vimage */
+        td->td_vimage = &vimage_0;
+#endif
+
 	/* Create sigacts. */
 	p->p_sigacts = sigacts_alloc();
 

==== //depot/projects/vimage/src/sys/kern/kern_fork.c#2 (text+ko) ====

@@ -39,6 +39,7 @@
 
 #include "opt_ktrace.h"
 #include "opt_mac.h"
+#include "opt_vimage.h"
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -65,6 +66,7 @@
 #include <sys/unistd.h>	
 #include <sys/sx.h>
 #include <sys/signalvar.h>
+#include <sys/vimage.h>
 
 #include <security/audit/audit.h>
 #include <security/mac/mac_framework.h>
@@ -75,7 +77,6 @@
 #include <vm/vm_extern.h>
 #include <vm/uma.h>
 
-
 #ifndef _SYS_SYSPROTO_H_
 struct fork_args {
 	int     dummy;
@@ -211,6 +212,16 @@
 	struct sigacts *newsigacts;
 	int error;
 
+#ifdef VIMAGE
+	/* XXX this should never happen! */
+	if (td->td_vimage == NULL) {
+		if (td->td_proc->p_pid == 0)
+			td->td_vimage = &vimage_0;
+		else
+			panic("td_vimage not set");
+	}
+#endif
+
 	/* Can't copy and clear. */
 	if ((flags & (RFFDG|RFCFDG)) == (RFFDG|RFCFDG))
 		return (EINVAL);
@@ -509,6 +520,10 @@
 	td2->td_sigstk = td->td_sigstk;
 	td2->td_sigmask = td->td_sigmask;
 
+	td2->td_vimage = td->td_vimage;
+	td2->td_vnetb = NULL; 		/* XXX */
+	td2->td_vnet_lpush = NULL;	/* XXX */
+
 	/*
 	 * Duplicate sub-structures as needed.
 	 * Increase reference counts on shared objects.

==== //depot/projects/vimage/src/sys/kern/kern_kse.c#2 (text+ko) ====

@@ -1109,6 +1109,12 @@
 	 */
 	bcopy(&td->td_startcopy, &td2->td_startcopy,
 	    __rangeof(struct thread, td_startcopy, td_endcopy));
+
+	/* XXX don't forget refcounting in vimage */
+	td2->td_vimage = td->td_vimage;
+	td2->td_vnetb = NULL;		/* XXX */
+	td2->td_vnet_lpush = NULL;	/* XXX */
+
 	thread_link(td2, ku->ku_ksegrp);
 	/* inherit parts of blocked thread's context as a good template */
 	cpu_set_upcall(td2, td);

==== //depot/projects/vimage/src/sys/kern/kern_linker.c#2 (text+ko) ====

@@ -30,6 +30,7 @@
 #include "opt_ddb.h"
 #include "opt_hwpmc_hooks.h"
 #include "opt_mac.h"
+#include "opt_vimage.h"
 
 #include <sys/param.h>
 #include <sys/kernel.h>
@@ -51,7 +52,10 @@
 #include <sys/vnode.h>
 #include <sys/syscallsubr.h>
 #include <sys/sysctl.h>
+#include <sys/vimage.h>
 
+#include <net/vnet.h>
+
 #include <security/mac/mac_framework.h>
 
 #include "linker_if.h"
@@ -858,6 +862,15 @@
 	if ((error = priv_check(td, PRIV_KLD_LOAD)) != 0)
 		return (error);
 
+#if 0
+	/* XXX should suser catch this for us? */
+	VNET_ASSERT(td->td_vimage == &vimage_0);
+#endif
+#ifdef VIMAGE
+	printf("kern_kldload: file=%s\n", file);
+#endif
+	CURVNETB_SET(td->td_vimage->v_vnetb);
+
 	/*
 	 * If file does not contain a qualified name or any dot in it
 	 * (kldname.ko, or kldname.ver.ko) treat it as an interface
@@ -885,6 +898,7 @@
 		*fileid = lf->id;
 unlock:
 	KLD_UNLOCK();
+	CURVNETB_RESTORE();
 	return (error);
 }
 
@@ -925,6 +939,12 @@
 	if ((error = priv_check(td, PRIV_KLD_UNLOAD)) != 0)
 		return (error);
 
+	/* XXX should suser catch this for us? */
+	VNET_ASSERT(td->td_vimage == &vimage_0);
+	/* XXX is this necessary at all? */
+	VNET_ASSERT(td == curthread);
+	CURVNETB_SET(td->td_vimage->v_vnetb);
+
 	KLD_LOCK();
 	lf = linker_find_file_by_id(fileid);
 	if (lf) {
@@ -955,6 +975,7 @@
 		PMC_CALL_HOOK(td, PMC_FN_KLD_UNLOAD, (void *) &pkm);
 #endif
 	KLD_UNLOCK();
+	CURVNETB_RESTORE();
 	return (error);
 }
 
@@ -1182,8 +1203,20 @@
 				break;
 			}
 		}
+#ifdef VIMAGE
+		if (lf == NULL) {
+			CURVNETB_SET(td->td_vimage->v_vnetb);
+			error = vi_symlookup(&lookup, symstr);
+			CURVNETB_RESTORE();
+			if (error == 0) {
+				error = copyout(&lookup, uap->data,
+				    sizeof(lookup));
+			}
+		}
+#else
 		if (lf == NULL)
 			error = ENOENT;
+#endif
 	}
 	KLD_UNLOCK();
 out:

==== //depot/projects/vimage/src/sys/kern/kern_synch.c#2 (text+ko) ====

@@ -38,6 +38,7 @@
 __FBSDID("$FreeBSD: src/sys/kern/kern_synch.c,v 1.285 2006/11/30 08:27:38 phk Exp $");
 
 #include "opt_ktrace.h"
+#include "opt_vimage.h"
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -61,9 +62,12 @@
 #include <sys/uio.h>
 #include <sys/ktrace.h>
 #endif
+#include <sys/vimage.h>
 
 #include <machine/cpu.h>
 
+#include <net/vnet.h>
+
 static void synch_setup(void *dummy);
 SYSINIT(synch_setup, SI_SUB_KICK_SCHEDULER, SI_ORDER_FIRST, synch_setup, NULL)
 
@@ -346,6 +350,7 @@
 	mtx_assert(&sched_lock, MA_OWNED | MA_NOTRECURSED);
 	td = curthread;			/* XXX */
 	p = td->td_proc;		/* XXX */
+	VNET_ASSERT(td->td_vimage); /* XXX */
 	KASSERT(!TD_ON_RUNQ(td), ("mi_switch: called by old code"));
 #ifdef INVARIANTS
 	if (!TD_ON_LOCK(td) && !TD_IS_RUNNING(td))

==== //depot/projects/vimage/src/sys/kern/kern_sysctl.c#2 (text+ko) ====

@@ -40,6 +40,7 @@
 
 #include "opt_compat.h"
 #include "opt_mac.h"
+#include "opt_vimage.h"
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -52,6 +53,7 @@
 #include <sys/mutex.h>
 #include <sys/sx.h>
 #include <sys/sysproto.h>
+#include <sys/vimage.h>
 
 #include <security/mac/mac_framework.h>
 
@@ -826,6 +828,42 @@
 }
 
 
+#ifdef VIMAGE
+int
+sysctl_handle_v_int(SYSCTL_HANDLER_V_ARGS)
+{
+	int error = 0;
+	void *ptr;
+
+	/*
+	 * Attempt to get a coherent snapshot by making a copy of the data.
+	 */
+	
+	switch (subs) {
+
+	case V_NET:
+		ptr = curthread->td_vimage->v_vnetb->mod_data[mod];
+		ptr = (void *) ((int) ptr + (int) arg1);
+		break;
+
+	default:
+		panic("unsupported module id %d", subs);
+	}
+
+	error = SYSCTL_OUT(req, ptr, sizeof(int));
+
+	if (error || !req->newptr)
+		return (error);
+
+	if (!ptr)
+		error = EPERM;
+	else
+		error = SYSCTL_IN(req, ptr, sizeof(int));
+	return (error);
+}
+#endif
+
+
 /*
  * Based on on sysctl_handle_int() convert milliseconds into ticks.
  */
@@ -972,6 +1010,45 @@
 	return (error);
 }
 
+#ifdef VIMAGE
+int
+sysctl_handle_v_opaque(SYSCTL_HANDLER_V_ARGS)
+{
+	int error, tries;
+	u_int generation;
+	struct sysctl_req req2;
+	void *ptr;
+
+	switch (subs) {
+
+	case V_NET:
+		ptr = curthread->td_vimage->v_vnetb->mod_data[mod];
+		ptr = (void *) ((int) ptr + (int) arg1);
+		break;
+
+	default:
+		panic("unsupported module id %d", subs);
+	}
+
+	tries = 0;
+	req2 = *req;
+retry:
+	generation = curthread->td_generation;
+	error = SYSCTL_OUT(req, ptr, arg2);
+	if (error)
+		return (error);
+	tries++;
+	if (generation != curthread->td_generation && tries < 3) {
+		*req = req2;
+		goto retry;
+	}
+
+	error = SYSCTL_IN(req, ptr, arg2);
+
+	return (error);
+}
+#endif
+
 /*
  * Transfer functions to/from kernel space.
  * XXX: rather untested at this point
@@ -1279,7 +1356,17 @@
 	if (error != 0)
 		return (error);
 #endif
+#ifndef VIMAGE
 	error = oid->oid_handler(oid, arg1, arg2, req);
+#else
+	if (oid->oid_v_subs) {
+		struct sysctl_v_oid *v_oid = (struct sysctl_v_oid *) oid;
+		error = v_oid->oid_handler(oid, arg1, arg2,
+					   req, oid->oid_v_subs,
+					   oid->oid_v_mod);
+	} else 
+		error = oid->oid_handler(oid, arg1, arg2, req);
+#endif
 
 	return (error);
 }
@@ -1374,6 +1461,8 @@
 	req.lock = REQ_LOCKED;
 
 	SYSCTL_LOCK();
+	CURVNETB_SET(curthread->td_vimage->v_vnetb);
+	VNET_ASSERT(td == curthread);
 
 	do {
 		req.oldidx = 0;
@@ -1384,6 +1473,7 @@
 	if (req.lock == REQ_WIRED && req.validlen > 0)
 		vsunlock(req.oldptr, req.validlen);
 
+	CURVNETB_RESTORE();
 	SYSCTL_UNLOCK();
 
 	if (error && error != ENOMEM)

==== //depot/projects/vimage/src/sys/kern/kern_thr.c#2 (text+ko) ====

@@ -205,6 +205,8 @@
 	newtd->td_proc = td->td_proc;
 	newtd->td_ucred = crhold(td->td_ucred);
 
+	newtd->td_vimage = td->td_vimage;
+
 	cpu_set_upcall(newtd, td);
 
 	if (ctx != NULL) { /* old way to set user context */

==== //depot/projects/vimage/src/sys/kern/kern_uuid.c#2 (text+ko) ====

@@ -27,6 +27,8 @@
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD: src/sys/kern/kern_uuid.c,v 1.11 2006/07/17 21:00:42 stefanf Exp $");
 
+#include "opt_vimage.h"
+
 #include <sys/param.h>
 #include <sys/endian.h>
 #include <sys/kernel.h>
@@ -37,7 +39,9 @@
 #include <sys/sysproto.h>
 #include <sys/systm.h>
 #include <sys/uuid.h>
+#include <sys/vimage.h>
 
+#include <net/vnet.h>
 #include <net/if.h>
 #include <net/if_dl.h>
 #include <net/if_types.h>
@@ -87,13 +91,14 @@
 static void
 uuid_node(uint16_t *node)
 {
+	INIT_VNET_NET(curvnetb);
 	struct ifnet *ifp;
 	struct ifaddr *ifa;
 	struct sockaddr_dl *sdl;
 	int i;
 
 	IFNET_RLOCK();
-	TAILQ_FOREACH(ifp, &ifnet, if_link) {
+	TAILQ_FOREACH(ifp, &V_ifnet, if_link) {
 		/* Walk the address list */
 		TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
 			sdl = (struct sockaddr_dl*)ifa->ifa_addr;

==== //depot/projects/vimage/src/sys/kern/kern_vimage.c#2 (text+ko) ====

@@ -1,0 +1,595 @@
+/*-
+ * Copyright (c) 2004, 2005, 2006 University of Zagreb
+ * Copyright (c) 2006 FreeBSD Foundation
+ *
+ * This software was developed by the University of Zagreb and the
+ * FreeBSD Foundation under sponsorship by the Stichting NLnet and the
+ * FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * XXX RCS tag goes here
+ */
+
+#include "opt_vimage.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/domain.h>
+#include <sys/protosw.h>
+#include <sys/kernel.h>
+#include <sys/sysproto.h>
+#include <sys/sysent.h>
+#include <sys/sockio.h>
+#include <sys/proc.h>
+#include <sys/linker.h>
+#include <sys/queue.h>
+#include <sys/socketvar.h>
+#include <sys/sysctl.h>
+#include <sys/vimage.h>
+#include <sys/vmmeter.h>
+
+#include <net/bpf.h>
+#include <net/if_types.h>
+#include <net/if_dl.h>
+#include <net/ethernet.h>
+
+MALLOC_DEFINE(M_VIMAGE, "vimage", "virtual image resource container");
+MALLOC_DEFINE(M_VNET, "vnet", "network stack control block");
+MALLOC_DEFINE(M_VPROCG, "vprocg", "process group control block");
+MALLOC_DEFINE(M_VCPU, "vcpu", "cpu resource control block");
+
+static void vi_destroy(struct vimage *);
+
+struct vimage vimage_0;
+struct vprocg vprocg_0;
+struct vcpu vcpu_0;
+struct vnet_base vnetb_0;
+
+struct vnet_base *vnetb_tbl[100]; /* XXX used in struct tcb */
+
+struct vimage_list_head vimage_head;
+struct vnetb_list_head vnetb_head;
+struct vprocg_list_head vprocg_head;
+struct vcpu_list_head vcpu_head;
+
+int last_vi_id = 0;
+
+static struct vnet_modlink vnet_modules[VNET_MOD_MAX];
+static TAILQ_HEAD(, vnet_modlink) vnet_modlink_head;
+
+int vnet_mod_register(modinfo)
+	struct vnet_modinfo *modinfo;
+{
+	/*
+	 * XXX we support only statically assigned module IDs at the time.
+	 * In principle modules should be able to be dynamically assigned
+	 * an ID at registration time.
+	 */
+	
+	if (modinfo->id < 0 || modinfo->id >= VNET_MOD_MAX)
+		return EFAULT;
+
+	if (vnet_modules[modinfo->id].modinfo != NULL)
+		return EEXIST;
+
+	vnet_modules[modinfo->id].modinfo = modinfo;
+	TAILQ_INSERT_TAIL(&vnet_modlink_head,
+			  &vnet_modules[modinfo->id], mod_le);
+
+	if (modinfo->i_attach) {
+		VNETB_ITERLOOP_BEGIN();
+			modinfo->i_attach();
+		VNETB_ITERLOOP_END();
+	}
+
+	return 0;
+}
+
+int vnet_mod_deregister(modinfo)
+	struct vnet_modinfo *modinfo;
+{
+	if (modinfo->id < 0 || modinfo->id >= VNET_MOD_MAX)
+		return EFAULT;
+
+	if (vnet_modules[modinfo->id].modinfo != modinfo)
+		return EFAULT;
+
+	if (modinfo->i_detach) {
+		VNETB_ITERLOOP_BEGIN();
+			modinfo->i_detach();
+		VNETB_ITERLOOP_END();
+	}
+
+	return 0;
+
+	vnet_modules[modinfo->id].modinfo = NULL;
+
+	return 0;
+}
+
+struct vimage *vnetb2vimage(vnetb)
+	struct vnet_base *vnetb;	
+{
+	struct vimage *vip;
+
+	LIST_FOREACH(vip, &vimage_head, vi_le)
+		if (vip->v_vnetb == vnetb)
+			return(vip);
+
+	panic("vnetb2vimage");	/* must never happen */
+}
+
+char *vnetb_name(vnetb)
+	struct vnet_base *vnetb;	
+{
+	return(vnetb2vimage(vnetb)->vi_name);
+}
+
+
+int
+vi_child_of(parent, child)
+	struct vimage *parent, *child;
+{
+	for (; child; child = child->vi_parent)
+		if (child == parent)
+			return (1);
+	return (0);
+}
+
+
+/*
+ * Move the interface to another vnet. The interface can be specified either
+ * by ifp argument, or by name contained in vi_req if NULL is passed as ifp.
+ * Similary, the target vnet can be specified either by vnet argument or
+ * by name. If vnet name equals to "-" or vi_req is set to NULL the
+ * interface is moved to the parent vnet.
+ */
+int
+vi_if_move(vi_req, ifp, vip)
+	struct vi_req *vi_req;
+	struct ifnet *ifp;
+	struct vimage *vip;
+{
+	struct vimage *new_vip;
+	struct vnet_base *new_vnetb = NULL;
+
+	if (vi_req == NULL || strcmp(vi_req->vi_name, "-") == 0) {
+		if (vip == &vimage_0)
+			return (ENXIO);
+		new_vnetb = vip->vi_parent->v_vnetb;
+	} else
+		LIST_FOREACH(new_vip, &vimage_head, vi_le) {
+			if (!vi_child_of(vip, new_vip))
+				continue;
+			if (strcmp(vi_req->vi_name, new_vip->vi_name) == 0) {
+				new_vnetb = new_vip->v_vnetb;
+				break;
+			}
+		}
+
+	if (new_vnetb == NULL)
+                return (ENXIO);
+
+#if 0 /* XXX deal with this later (tm) */
+	if (ifp == NULL)
+        	ifp = ifunit(vi_req->vi_chroot, cur_vnetb);
+	if (ifp == NULL)
+                return (ENXIO);
+
+	if (vi_req != NULL && ifunit(vi_req->vi_parent_name, new_vnetb) != NULL)	
+		return (EEXIST);
+
+	/* Loopback interfaces cannot be moved across network stacks */
+        if (ifp == &cur_vnetb->loif)
+		return (EPERM);
+
+	/*
+	 * This is tricky. First we have to detach the interface,
+	 * and then reattach it to the target vnet. Before doing
+	 * that, we reassing the interface unit number to look nice
+	 * in the target vnetb.
+	 */
+        switch (ifp->if_type) {
+        case IFT_ETHER:		/* all these types use struct arpcom */
+        case IFT_FDDI:
+        case IFT_XETHER:
+        case IFT_ISO88025:
+        case IFT_L2VLAN:
+		ether_ifdetach(ifp, ETHER_BPF_SUPPORTED);
+		break;
+        default:
+		if_detach(ifp);
+        }
+
+	ifp->if_vnetb = new_vnetb;
+
+	if (ifp->if_rname == NULL) {
+		ifp->if_rname = ifp->if_name;
+		ifp->if_runit = ifp->if_unit;
+	}
+
+	unit = 0;
+	if (vip->vi_parent != NULL &&
+	    new_vnetb == vip->vi_parent->v_vnetb &&
+	    ifp->if_rname != NULL) {
+		ifp->if_name = ifp->if_rname;
+		unit = ifp->if_runit;
+	}
+
+	if (vi_req != NULL && strlen(vi_req->vi_parent_name) && unit == 0 ) {
+		char c;
+		const char *cp;
+		unsigned len, m;
+
+		len = strlen(vi_req->vi_parent_name);
+		if (len < 2 || len > IFNAMSIZ)
+			return (EINVAL);
+		cp = vi_req->vi_parent_name + len - 1;
+		c = *cp;
+		if (c < '0' || c > '9')
+			return (EINVAL);            /* trailing garbage */
+		m = 1;
+		do {
+			if (cp == vi_req->vi_parent_name)
+				return (EINVAL);    /* no interface name */
+			unit += (c - '0') * m;
+			if (unit > 1000000)
+				return (EINVAL);    /* number is unreasonable */
+			m *= 10;
+			c = *--cp;
+		} while (c >= '0' && c <= '9');
+		len = cp - vi_req->vi_parent_name + 1;
+		bcopy(vi_req->vi_parent_name, ifp->if_fname, len);
+		ifp->if_fname[len] = '\0';
+		ifp->if_name = ifp->if_fname;
+	} else {
+		do {
+			TAILQ_FOREACH(ifp1, &new_vnetb->ifnet, if_link) {
+				if (strcmp(ifp->if_name, ifp1->if_name))
+					continue;
+				if (unit == ifp1->if_unit)
+					break;
+			}
+			unit++;
+		} while (ifp1);
+		unit--;
+	}
+
+	ifp->if_unit = unit;
+        switch (ifp->if_type) {
+        case IFT_ETHER:		/* all these types use struct arpcom */
+        case IFT_FDDI:
+        case IFT_XETHER:
+        case IFT_ISO88025:
+        case IFT_L2VLAN:
+		ether_ifattach(ifp, ETHER_BPF_SUPPORTED);
+		break;
+        default:
+		if_attach(ifp);
+        }
+	getmicrotime(&ifp->if_lastchange);
+
+	if (vi_req != NULL)
+		sprintf(vi_req->vi_chroot, "%s%d", ifp->if_name, ifp->if_unit);
+
+#endif
+	return (0);
+}
+
+
+int
+vi_td_ioctl(cmd, vi_req, td)
+	u_long cmd;
+	struct vi_req *vi_req;
+	struct thread *td;
+{
+	int error;
+	struct vimage *vip = td->td_vimage;
+	struct vimage *vip_r = NULL;
+	struct vimage *tvip;
+
+	error = suser(td);
+	if (error)
+		return (error);
+
+	if (strlen(vi_req->vi_name)) {
+		LIST_FOREACH(tvip, &vimage_head, vi_le)
+			if (strcmp(vi_req->vi_name, tvip->vi_name)==0) {
+				vip_r = tvip;
+				break;
+			}
+		if (vip_r == NULL && !(vi_req->req_action & VI_CREATE)) {
+               		return (ESRCH);
+		}
+		if (vip_r != NULL && vi_req->req_action & VI_CREATE) {
+               		return (EADDRINUSE);
+		}
+		if (vi_req->req_action == VI_GETNEXT) {
+vi_getnext_loop:
+			if ((vip_r = LIST_NEXT(vip_r, vi_le)) == 0)
+				vip_r = LIST_FIRST(&vimage_head);
+			if (vip_r == vip) {
+				return (ESRCH);
+			}
+			if (!vi_child_of(vip, vip_r))
+				goto vi_getnext_loop;
+		}
+
+	} else
+		vip_r = vip;
+
+	if (vip_r && vip != &vimage_0 && !vi_child_of(vip, vip_r)) {
+		return (EPERM);
+	}
+
+	switch (cmd) {
+
+	case SIOCGPVIMAGE:
+		vi_req->vi_id = vip_r->vi_id;
+		bcopy(&vip_r->vi_name, &vi_req->vi_name,
+			sizeof (vi_req->vi_name));
+		if (vip_r->vi_parent)
+			bcopy(&vip_r->vi_parent->vi_name,
+				&vi_req->vi_parent_name,
+				sizeof (vi_req->vi_parent_name));
+		else
+			vi_req->vi_parent_name[0] = 0;
+		vi_req->vi_if_count = vip_r->v_vnetb->ifccnt;
+		vi_req->vi_sock_count = vip_r->v_vnetb->sockcnt;
+		break;
+
+	case SIOCSPVIMAGE:
+		if (vi_req->req_action == VI_DESTROY) {
+			vi_destroy(vip_r);
+			break;
+		}
+
+		if (vi_req->req_action == VI_SWITCHTO) {
+			td->td_vimage = vip_r;
+			break;
+		}
+
+		if (vi_req->req_action & VI_CREATE) {
+			vip_r = vi_alloc(vi_req->vi_name, vi_req->vi_maxsockets,
+					vi_req->vi_tsc_hashs,
+					vi_req->vi_tsc_buckl);
+			if (vip_r == NULL)
+				return (ENOMEM);
+
+			vip_r->vi_parent = vip;
+		}
+
+		if (vip == vip_r && vip != &vimage_0) {
+       			return (EPERM);
+		}
+	}
+
+	return (error);
+}
+
+
+int
+vi_symlookup(lookup, symstr)
+	struct kld_sym_lookup *lookup;
+	char *symstr;
+{
+	int i;
+
+	for (i = 0; i < VNET_MOD_MAX; i++) {
+		struct vnet_symmap *mapentry;
+
+		if (vnet_modules[i].modinfo == NULL ||
+		    vnet_modules[i].modinfo->symmap == NULL)
+			continue;
+
+		for (mapentry = vnet_modules[i].modinfo->symmap;
+		     mapentry->name != NULL; mapentry++) {
+			if (strcmp(symstr, mapentry->name) == 0) {
+				lookup->symvalue =
+					(int) curvnetb->mod_data[i];
+				lookup->symvalue += mapentry->offset;
+				lookup->symsize = mapentry->size;
+				return 0;
+			}
+		}
+	}
+
+	return ENOENT;
+}
+
+
+struct vimage *
+vi_alloc(name, maxsock, tsc_hashs, tsc_buckl)
+	char *name;
+	int maxsock, tsc_hashs, tsc_buckl;
+{
+	struct vimage *vip;
+        struct vnet_base *vnetb;
+        struct vprocg *vprocg;
+        struct vcpu *vcpu;
+	struct domain *dp;
+
+printf("vi_alloc: %s\n", name);
+	/* A brute force check whether there's enough mem for a new vimage */
+        vip = malloc(127*1024, M_VIMAGE, M_NOWAIT); /* XXX aaaargh... */
+        if (vip == NULL)
+		return NULL;
+
+        vip = realloc(vip, sizeof(struct vimage), M_VIMAGE, M_NOWAIT);
+        if (vip == NULL)
+                panic("vi_alloc: malloc failed for vimage \"%s\"\n", name);
+        bzero(vip, sizeof(struct vimage));
+        vip->vi_id = last_vi_id++;
+
+        vnetb = malloc(sizeof(struct vnet_base), M_VNET, M_NOWAIT);
+        if (vnetb == NULL)
+                panic("vi_alloc: malloc failed for vnetb \"%s\"\n", name);
+        bzero(vnetb, sizeof(struct vnet_base));
+	vip->v_vnetb = vnetb;
+
+        vprocg = malloc(sizeof(struct vprocg), M_VPROCG, M_NOWAIT);
+        if (vprocg == NULL)
+                panic("vi_alloc: malloc failed for vprocg \"%s\"\n", name);
+        bzero(vprocg, sizeof(struct vprocg));
+	vip->v_procg = vprocg;
+
+        vcpu = malloc(sizeof(struct vcpu), M_VCPU, M_NOWAIT);
+        if (vcpu == NULL)
+                panic ("vi_alloc: malloc failed for vcpu \"%s\"\n", name);
+        bzero (vcpu, sizeof(struct vcpu));
+	vip->v_cpu = vcpu;
+
+        /* Some initialization stuff... */
+	sprintf(vip->vi_name, "%s", name);
+
+	/*

>>> TRUNCATED FOR MAIL (1000 lines) <<<


More information about the p4-projects mailing list