vnet.c
来自「xen虚拟机源代码安装包」· C语言 代码 · 共 700 行 · 第 1/2 页
C
700 行
/* * Copyright (C) 2004, 2005 Mike Wray <mike.wray@hp.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free software Foundation, Inc., * 59 Temple Place, suite 330, Boston, MA 02111-1307 USA * */#ifdef __KERNEL__#include <linux/config.h>#include <linux/module.h>#include <linux/types.h>#include <linux/kernel.h>#include <linux/version.h>#include <linux/errno.h>#include <linux/string.h>#include <linux/spinlock.h>#include <linux/net.h>#include <linux/in.h>#include <linux/inet.h>#include <linux/netdevice.h>#include <linux/etherdevice.h>#include <net/ip.h>#include <net/protocol.h>#include <net/route.h>#include <linux/skbuff.h>#include <net/checksum.h>#else #include <netinet/in.h>#include <arpa/inet.h>#include "sys_kernel.h"#include "spinlock.h"#include "skbuff.h"#include <linux/ip.h> // For struct iphdr.extern int netif_rx(struct sk_buff *skb);#endif#include <tunnel.h>#include <sa.h>#include <varp.h>#include <if_varp.h>#include <esp.h>#include <etherip.h>#include <random.h>#include <skb_context.h>#include <skb_util.h>#include <vnet_dev.h>#include <vnet.h>#include <vnet_forward.h>#include <vif.h>#include <vnet_ioctl.h>#include <sa.h>#ifdef __KERNEL__#include <sa_algorithm.h>#endif#include "allocate.h"#include "iostream.h"#include "hash_table.h"#include "sys_net.h"#include "sys_string.h"#define MODULE_NAME "VNET"#define DEBUG 1#undef DEBUG#include "debug.h"/** Default vnet security level. */int vnet_security_default = SA_AUTH ; //| SA_CONF;/** The physical vnet. */Vnet *vnet_physical = NULL;/** Table of vnets indexed by id. */HashTable *vnet_table = NULL;rwlock_t vnet_lock = RW_LOCK_UNLOCKED;#define vnet_table_read_lock(flags) read_lock_irqsave(&vnet_lock, flags)#define vnet_table_read_unlock(flags) read_unlock_irqrestore(&vnet_lock, flags)#define vnet_table_write_lock(flags) write_lock_irqsave(&vnet_lock, flags)#define vnet_table_write_unlock(flags) write_unlock_irqrestore(&vnet_lock, flags)/** Decrement reference count, freeing if zero. * * @param info vnet (OK if null) */void Vnet_decref(Vnet *info){ if(!info) return; if(atomic_dec_and_test(&info->refcount)){ deallocate(info); }}/** Increment reference count. * * @param info vnet (OK if null) */void Vnet_incref(Vnet *info){ if(!info) return; atomic_inc(&info->refcount);}void Vnet_print(Vnet *info, IOStream *io){ char vnetbuf[VNET_ID_BUF]; char *security; if(info->security & SA_CONF){ security = "conf"; } else if(info->security & SA_AUTH){ security = "auth"; } else { security = "none"; } IOStream_print(io, "(vnet"); IOStream_print(io, " (id %s)", VnetId_ntoa(&info->vnet, vnetbuf)); IOStream_print(io, " (vnetif %s)", info->device); IOStream_print(io, " (security %s)", security); IOStream_print(io, " (header %d)", info->header_n); IOStream_print(io, ")");}void vnet_print(IOStream *io){ HashTable_for_decl(entry); Vnet *info; unsigned long flags; vnet_table_read_lock(flags); HashTable_for_each(entry, vnet_table){ info = entry->value; Vnet_print(info, io); IOStream_print(io, "\n"); } vnet_table_read_unlock(flags);}/** Allocate a vnet, setting reference count to 1. * * @param info return parameter for vnet * @return 0 on success, error code otherwise */int Vnet_alloc(Vnet **info){ int err = 0; *info = ALLOCATE(Vnet); if(*info){ atomic_set(&(*info)->refcount, 1); } else { err = -ENOMEM; } return err;}/** Create the virtual interface for a vnet. * * @param info vnet * @return 0 on success, error code otherwise */int Vnet_create(Vnet *info){ int err = 0; err = vnet_dev_add(info); if(err) goto exit; err = Vnet_add(info); exit: return err;} /** Add a vnet to the table under its vnet id. * * @param info vnet to add * @return 0 on success, error code otherwise */int Vnet_add(Vnet *info){ int err = 0; HTEntry *entry = NULL; unsigned long flags; if(Vnet_lookup(&info->vnet, NULL) == 0){ //todo: Delete existing vnet info? err = -EEXIST; goto exit; } Vnet_incref(info); vnet_table_write_lock(flags); entry = HashTable_add(vnet_table, &info->vnet, info); vnet_table_write_unlock(flags); if(!entry){ err = -ENOMEM; vnet_dev_remove(info); Vnet_decref(info); } exit: return err;}/** Remove a vnet from the table. * Also removes all vifs and varp entries for the vnet. * * @param vnet id of vnet to remove * @return number of vnets removed */int Vnet_del(VnetId *vnet){ int count; unsigned long flags; Vnet *info; vnet_table_write_lock(flags); info = HashTable_get(vnet_table, vnet); count = HashTable_remove(vnet_table, vnet); vnet_table_write_unlock(flags); varp_remove_vnet(vnet); vif_remove_vnet(vnet); if(info){ // Can't do this in the hashtable entry free function because it runs // while we hold the vnet table lock, and the vnet tidy up calls // vnet_dev_remove(), which calls unregister_netdev(), which schedules. vnet_dev_remove(info); Vnet_decref(info); } return count;}/** Lookup a vnet by id. * References the vnet on success - the caller must decref. * * @param vnet vnet id * @param pinfo return parameter for vnet (or NULL) * @return 0 on sucess, -ENOENT if no vnet found */int Vnet_lookup(VnetId *vnet, Vnet **pinfo){ int err = 0; unsigned long flags; Vnet *info; vnet_table_read_lock(flags); info = HashTable_get(vnet_table, vnet); if(info){ if(pinfo){ Vnet_incref(info); } } else { err = -ENOENT; } vnet_table_read_unlock(flags); if(pinfo){ *pinfo = (err ? NULL : info); } return err;}static int vnet_key_equal_fn(void *k1, void *k2){ return memcmp(k1, k2, sizeof(VnetId)) == 0;}static Hashcode vnet_key_hash_fn(void *k){ return hash_hvoid(0, k, sizeof(VnetId));}/** Free an entry in the vnet table. * * @param table containing table * @param entry to free */static void vnet_entry_free_fn(HashTable *table, HTEntry *entry){ if(!entry) return; HTEntry_free(entry);}void vnet_table_free(void){ HashTable *vnt; HashTable_for_decl(entry); vnt = vnet_table; if(!vnt) return; vnet_table = NULL; HashTable_for_each(entry, vnt){ Vnet *info = entry->value; vnet_dev_remove(info); Vnet_decref(info); } HashTable_free(vnt);}int vnet_table_init(void){ int err = 0; vnet_table = HashTable_new(0); if(!vnet_table){ err = -ENOMEM; goto exit; } vnet_table->key_size = sizeof(VnetId); vnet_table->key_equal_fn = vnet_key_equal_fn; vnet_table->key_hash_fn = vnet_key_hash_fn; vnet_table->entry_free_fn = vnet_entry_free_fn; err = Vnet_alloc(&vnet_physical); if(err) goto exit; vnet_physical->vnet = toVnetId(VNET_PHYS); vnet_physical->security = 0; err = Vnet_add(vnet_physical); exit: if(err){ vnet_table_free(); } return err;}/** Setup some vnet entries (for testing). * Vnet 1 is physical, vnets 2 to 10 are insecure, vnets above * 10 are secure. * * @return 0 on success, negative error code otherwise */static int vnet_setup(void){ int err = 0; int i, n = 3; int security = vnet_security_default; uint32_t vnetid; Vnet *vnet;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?