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 + -
显示快捷键?