Date: Fri, 1 Dec 2006 21:06:44 GMT From: Marko Zec <zec@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 110833 for review Message-ID: <200612012106.kB1L6iXK044193@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=110833 Change 110833 by zec@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) <<<
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200612012106.kB1L6iXK044193>