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