⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tunnel.c

📁 xen虚拟机源代码安装包
💻 C
字号:
/* * 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/init.h>#include <linux/skbuff.h>#include <linux/spinlock.h>#else#include "sys_kernel.h"#include "spinlock.h"#include "skbuff.h"#endif#include <tunnel.h>#include <vnet.h>#include <varp.h>#include "hash_table.h"#define MODULE_NAME "VNET"#define DEBUG 1#undef DEBUG#include "debug.h"/** Table of tunnels, indexed by vnet and addr. */HashTable *tunnel_table = NULL;rwlock_t tunnel_table_lock = RW_LOCK_UNLOCKED;#define tunnel_read_lock(flags)    read_lock_irqsave(&tunnel_table_lock, (flags))#define tunnel_read_unlock(flags)  read_unlock_irqrestore(&tunnel_table_lock, (flags))#define tunnel_write_lock(flags)   write_lock_irqsave(&tunnel_table_lock, (flags))#define tunnel_write_unlock(flags) write_unlock_irqrestore(&tunnel_table_lock, (flags))void Tunnel_free(Tunnel *tunnel){    tunnel->type->close(tunnel);    Tunnel_decref(tunnel->base);    kfree(tunnel);}void Tunnel_print(Tunnel *tunnel){    if(tunnel){        iprintf("Tunnel<%p base=%p ref=%02d type=%s>\n",               tunnel,               tunnel->base,               atomic_read(&tunnel->refcount),               tunnel->type->name);        if(tunnel->base){            Tunnel_print(tunnel->base);        }    } else {        iprintf("Tunnel<%p base=%p ref=%02d type=%s>\n",               NULL, NULL, 0, "ip");    }}int Tunnel_create(TunnelType *type, VnetId *vnet, VarpAddr *addr,                  Tunnel *base, Tunnel **val){    int err = 0;    Tunnel *tunnel = NULL;    if(!type || !type->open || !type->send || !type->close){        err = -EINVAL;        goto exit;    }    tunnel = kmalloc(sizeof(Tunnel), GFP_ATOMIC);    if(!tunnel){        err = -ENOMEM;        goto exit;    }    atomic_set(&tunnel->refcount, 1);    tunnel->key.vnet = *vnet;    tunnel->key.addr = *addr;    tunnel->type = type;    tunnel->data = NULL;    tunnel->send_stats = (TunnelStats){};    Tunnel_incref(base);    tunnel->base = base;    err = type->open(tunnel);  exit:    if(err && tunnel){        Tunnel_decref(tunnel);        tunnel = NULL;    }    *val = tunnel;    dprintf("< err=%d\n", err);    return err;}void TunnelStats_update(TunnelStats *stats, int len, int err){    dprintf(">len=%d  err=%d\n", len, err);    if(err){        stats->dropped_bytes += len;        stats->dropped_packets++;    } else {        stats->bytes += len;        stats->packets++;    }    dprintf("<\n");}static inline Hashcode tunnel_table_key_hash_fn(void *k){    return hash_hvoid(0, k, sizeof(TunnelKey));}static int tunnel_table_key_equal_fn(void *k1, void *k2){    return memcmp(k1, k2, sizeof(TunnelKey)) == 0;}static void tunnel_table_entry_free_fn(HashTable *table, HTEntry *entry){    Tunnel *tunnel;    if(!entry) return;    tunnel = entry->value;    Tunnel_decref(tunnel);    HTEntry_free(entry);}int Tunnel_init(void){    int err = 0;    dprintf(">\n");    tunnel_table = HashTable_new(0);    if(!tunnel_table){        err = -ENOMEM;        goto exit;    }    tunnel_table->entry_free_fn = tunnel_table_entry_free_fn;    tunnel_table->key_size = sizeof(TunnelKey);    tunnel_table->key_hash_fn = tunnel_table_key_hash_fn;    tunnel_table->key_equal_fn = tunnel_table_key_equal_fn;  exit:    dprintf("< err=%d\n", err);    return err;}    /** Lookup tunnel state by vnet and destination. * The caller must drop the tunnel reference when done. * * @param vnet vnet * @param addr destination address * @return 0 on success */int Tunnel_lookup(VnetId *vnet, VarpAddr *addr, Tunnel **tunnel){    unsigned long flags;    TunnelKey key = { .vnet = *vnet, .addr = *addr };    dprintf(">\n");    tunnel_read_lock(flags);    *tunnel = HashTable_get(tunnel_table, &key);    tunnel_read_unlock(flags);    Tunnel_incref(*tunnel);    dprintf("< tunnel=%p\n", *tunnel);    return (*tunnel ? 0 : -ENOENT);}/** Get a tunnel to a given vnet and destination, creating * a tunnel if necessary. * The caller must drop the tunnel reference when done. * * @param vnet vnet * @param addr destination address * @param ctor tunnel constructor * @parma ptunnel return parameter for the tunnel * @return 0 on success */int Tunnel_open(VnetId *vnet, VarpAddr *addr,                int (*ctor)(VnetId *vnet, VarpAddr *addr, Tunnel **ptunnel),                Tunnel **ptunnel){    int err = 0;    Tunnel *tunnel = NULL;    unsigned long flags;    TunnelKey key = { .vnet = *vnet, .addr = *addr };    tunnel_write_lock(flags);    tunnel = HashTable_get(tunnel_table, &key);    if(!tunnel){        err = ctor(vnet, addr, &tunnel);        if(err) goto exit;        if(!HashTable_add(tunnel_table, tunnel, tunnel)){            err = -ENOMEM;            goto exit;        }    }  exit:    tunnel_write_unlock(flags);    if(err){        Tunnel_decref(tunnel);        *ptunnel = NULL;    } else {        Tunnel_incref(tunnel);        *ptunnel = tunnel;    }    return err;}int Tunnel_add(Tunnel *tunnel){    int err = 0;    unsigned long flags;    dprintf(">\n");    tunnel_write_lock(flags);    if(HashTable_add(tunnel_table, tunnel, tunnel)){        Tunnel_incref(tunnel);       } else {        err = -ENOMEM;    }    tunnel_write_unlock(flags);    dprintf("< err=%d\n", err);    return err;}int Tunnel_del(Tunnel *tunnel){    int err;    unsigned long flags;    tunnel_write_lock(flags);    err = HashTable_remove(tunnel_table, tunnel);    tunnel_write_unlock(flags);    return err;}/** Do tunnel send processing on a packet. * * @param tunnel tunnel state * @param skb packet * @return 0 on success, error code otherwise */int Tunnel_send(Tunnel *tunnel, struct sk_buff *skb){    int err = 0;    dprintf("> tunnel=%p skb=%p\n", tunnel, skb);    if(tunnel){        int len = skb->len;        dprintf("> type=%s type->send...\n", tunnel->type->name);        // Must not refer to skb after sending - might have been freed.        err = tunnel->type->send(tunnel, skb);        TunnelStats_update(&tunnel->send_stats, len, err);    } else {        err = skb_xmit(skb);    }    dprintf("< err=%d\n", err);    return err;}int __init tunnel_module_init(void){    return Tunnel_init();}void __exit tunnel_module_exit(void){    unsigned long flags;    tunnel_write_lock(flags);    if(tunnel_table){        HashTable_free(tunnel_table);        tunnel_table = NULL;    }    tunnel_write_unlock(flags);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -