Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Merge branch 'devel' of ssh://palacios@newskysaw/home/palacios/palacios into devel
Jack Lange [Wed, 25 May 2011 20:36:04 +0000 (15:36 -0500)]
17 files changed:
linux_module/Makefile
linux_module/palacios-dev.c
linux_module/palacios-graphics-console.c
linux_module/palacios-packet.h
linux_module/palacios-socket.c
linux_module/palacios-socket.h
linux_module/palacios-vnet-brg.c [new file with mode: 0644]
linux_module/palacios-vnet-ctrl.c [moved from linux_module/palacios-vnet-bridge.c with 53% similarity]
linux_module/palacios-vnet.c
linux_module/palacios-vnet.h
palacios/include/palacios/vmm_ethernet.h
palacios/include/vnet/vnet.h
palacios/include/vnet/vnet_host.h
palacios/src/devices/lnx_virtio_nic.c
palacios/src/devices/vnet_nic.c
palacios/src/vnet/vnet_core.c
palacios/src/vnet/vnet_host.c

index a1a4349..b3bd558 100644 (file)
@@ -34,7 +34,9 @@ ifdef V3_CONFIG_EXT_INSPECTOR
 endif
 
 ifdef V3_CONFIG_VNET
-       v3vee-objs += palacios-vnet.o palacios-vnet-bridge.o
+       v3vee-objs +=   palacios-vnet.o \
+                       palacios-vnet-ctrl.o   \
+                       palacios-vnet-brg.o
 endif
 
 ifdef V3_CONFIG_PACKET
index 6645860..cf8e0fe 100644 (file)
@@ -292,7 +292,7 @@ static int __init v3_init(void) {
 #endif
 
 #ifdef V3_CONFIG_VNET
-    palacios_init_vnet();
+    palacios_vnet_init();
 #endif
 
 #ifdef V3_CONFIG_HOST_DEVICE
@@ -352,6 +352,18 @@ static void __exit v3_exit(void) {
     palacios_deinit_stream();
 #endif
 
+#ifdef V3_CONFIG_SOCKET
+    palacios_socket_deinit();
+#endif
+
+#ifdef V3_CONFIG_PACKET
+    palacios_deinit_packet(NULL);
+#endif
+
+#ifdef V3_CONFIG_VNET
+    palacios_vnet_deinit();
+#endif
+
     palacios_deinit_mm();
 
     printk("Palacios Module Mallocs = %d, Frees = %d\n", mod_allocs, mod_frees);
index 0b03b62..3cd70c9 100644 (file)
@@ -19,6 +19,7 @@
 #include "palacios.h"
 #include "palacios-graphics-console.h"
 
+#include <linux/vmalloc.h>
 
 /*
 
@@ -57,7 +58,7 @@ static v3_graphics_console_t g_open(void * priv_data,
     printk("palacios: allocating %u bytes for %u by %u by %u buffer\n",
           mem, desired_spec->width, desired_spec->height, desired_spec->bytes_per_pixel);
 
-    gc->data = kmalloc(mem,GFP_KERNEL);
+    gc->data = vmalloc(mem);
 
     if (!(gc->data)) { 
        printk("palacios: unable to allocate memory for frame buffer\n");
index 476f473..9b26e40 100644 (file)
@@ -7,5 +7,6 @@
 #define __PALACIOS_PACKET_H__
 
 int palacios_init_packet(const char * eth_dev);
+int palacios_deinit_packet(void);
 
 #endif
index 28b613f..8d17d8f 100644 (file)
@@ -436,3 +436,10 @@ int palacios_socket_init( void ) {
        INIT_LIST_HEAD(&global_sockets);
        return 0;
 }
+
+void palacios_socket_deinit( void ) {
+    if (!list_empty(&(global_sockets))) {
+       printk("Error removing module with open sockets\n");
+    }
+}
+
index 098b6dd..394802e 100644 (file)
@@ -7,5 +7,6 @@
 #define __PALACIOS_SOCKET_H__
 
 int palacios_socket_init(void);
+int palacios_socket_deinit(void);
 
 #endif
diff --git a/linux_module/palacios-vnet-brg.c b/linux_module/palacios-vnet-brg.c
new file mode 100644 (file)
index 0000000..e87d422
--- /dev/null
@@ -0,0 +1,520 @@
+/* 
+   Palacios VNET Host Bridge
+   (c) Lei Xia, 2010
+ */
+#include <linux/spinlock.h>
+#include <linux/seq_file.h>
+#include <linux/proc_fs.h>
+#include <asm/uaccess.h>
+#include <linux/inet.h>
+#include <linux/kthread.h>
+
+#include <linux/netdevice.h>
+#include <linux/ip.h>
+#include <linux/in.h>
+#include <linux/net.h>
+#include <linux/string.h>
+#include <linux/preempt.h>
+#include <linux/sched.h>
+#include <asm/msr.h>
+
+#include <vnet/vnet.h>
+#include <vnet/vnet_hashtable.h>
+#include "palacios-vnet.h"
+
+#define VNET_SERVER_PORT 9000
+
+struct vnet_link {
+    uint32_t dst_ip;
+    uint16_t dst_port;
+    
+    struct socket * sock;
+    struct sockaddr_in sock_addr;
+    vnet_brg_proto_t sock_proto;
+
+    struct nic_statistics stats;
+
+    uint32_t idx;
+
+    struct list_head node;
+};
+
+
+struct vnet_brg_state {
+    uint8_t status;
+
+    uint32_t num_links;
+    uint32_t link_idx;
+    struct list_head link_list;
+    struct hashtable *ip2link;
+
+    spinlock_t lock;
+
+    struct socket * serv_sock;
+    struct sockaddr_in serv_addr;
+    vnet_brg_proto_t serv_proto;
+       
+    struct task_struct * serv_thread;
+
+    void * brg_data; /* private data from vnet_core */
+
+    struct vnet_brg_stats stats;
+};
+
+
+static struct vnet_brg_state vnet_brg_s;
+
+
+int vnet_brg_stats(struct vnet_brg_stats * stats){
+    memcpy(stats, &(vnet_brg_s.stats), sizeof(*stats));
+
+    return 0;
+}
+
+static inline struct vnet_link * _link_by_ip(uint32_t ip) {
+    return (struct vnet_link *)vnet_htable_search(vnet_brg_s.ip2link, (addr_t)&ip);
+}
+
+static inline struct vnet_link * _link_by_idx(int idx) {
+    struct vnet_link * link = NULL;
+
+    list_for_each_entry(link, &(vnet_brg_s.link_list), node) {
+               
+       if (link->idx == idx) {
+           return link;
+       }
+    }
+    return NULL;
+}
+
+
+static void _delete_link(struct vnet_link * link){
+    unsigned long flags;
+
+    link->sock->ops->release(link->sock);
+
+    spin_lock_irqsave(&(vnet_brg_s.lock), flags);
+    list_del(&(link->node));
+    vnet_htable_remove(vnet_brg_s.ip2link, (addr_t)&(link->dst_ip), 0);
+    vnet_brg_s.num_links --;
+    spin_unlock_irqrestore(&(vnet_brg_s.lock), flags);
+
+    printk("VNET Bridge: Link deleted, ip 0x%x, port: %d, idx: %d\n", 
+          link->dst_ip, 
+          link->dst_port, 
+          link->idx);
+
+    kfree(link);
+    link = NULL;
+}
+
+void vnet_brg_delete_link(uint32_t idx){
+    struct vnet_link * link = _link_by_idx(idx);
+
+    if(link){
+       _delete_link(link);
+    }
+}
+
+static void deinit_links_list(void){
+    struct vnet_link * link;
+
+    list_for_each_entry(link, &(vnet_brg_s.link_list), node) {
+       _delete_link(link);
+    }
+}
+
+static uint32_t _create_link(struct vnet_link * link) {
+    int err;
+    unsigned long flags;
+    int protocol;
+
+    switch(link->sock_proto){
+       case UDP:
+           protocol = IPPROTO_UDP;
+           break;
+       case TCP:
+           protocol = IPPROTO_TCP;
+           break;
+
+       default:
+           printk("Unsupported VNET Server Protocol\n");
+           return -1;
+    }
+   
+    if ((err = sock_create(AF_INET, SOCK_DGRAM, protocol, &link->sock)) < 0) {
+       printk("Could not create socket for VNET Link, error %d\n", err);
+       return -1;
+    }
+
+    memset(&link->sock_addr, 0, sizeof(struct sockaddr));
+
+    link->sock_addr.sin_family = AF_INET;
+    link->sock_addr.sin_addr.s_addr = link->dst_ip;
+    link->sock_addr.sin_port = htons(link->dst_port);
+
+    if ((err = link->sock->ops->connect(link->sock, (struct sockaddr *)&(link->sock_addr), sizeof(struct sockaddr), 0) < 0)) {
+       printk("Could not connect to remote VNET Server, error %d\n", err);
+       return -1;
+    }
+
+    spin_lock_irqsave(&(vnet_brg_s.lock), flags);
+    list_add(&(link->node), &(vnet_brg_s.link_list));
+    vnet_brg_s.num_links ++;
+    link->idx = ++ vnet_brg_s.link_idx;
+    vnet_htable_insert(vnet_brg_s.ip2link, (addr_t)&(link->dst_ip), (addr_t)link);
+    spin_unlock_irqrestore(&(vnet_brg_s.lock), flags);
+
+    printk("VNET Bridge: Link created, ip 0x%x, port: %d, idx: %d, link: %p, protocol: %s\n", 
+          link->dst_ip, 
+          link->dst_port, 
+          link->idx, 
+          link,
+          ((link->sock_proto==UDP)?"UDP":"TCP"));
+
+    return link->idx;
+}
+
+
+uint32_t vnet_brg_add_link(uint32_t ip, uint16_t port, vnet_brg_proto_t proto){
+     struct vnet_link * new_link = NULL;
+     uint32_t idx;
+
+     new_link = kmalloc(sizeof(struct vnet_link), GFP_KERNEL);
+     if (!new_link) {
+       return -1;
+     }
+     memset(new_link, 0, sizeof(struct vnet_link));
+
+     new_link->dst_ip = ip;
+     new_link->dst_port = port;
+     new_link->sock_proto = proto;
+
+     idx = _create_link(new_link);
+     if (idx < 0) {
+       printk("Could not create link\n");
+       kfree(new_link);
+       return -1;
+     }
+
+     return idx;
+}
+
+
+int vnet_brg_link_stats(uint32_t link_idx, struct nic_statistics * stats){
+     struct vnet_link * link;
+
+     link = _link_by_idx(link_idx);
+     if(!link){
+        return -1;
+     }
+
+     memcpy(stats, &(link->stats), sizeof(*stats));
+
+     return 0;
+}
+     
+
+static int 
+_udp_send(struct socket * sock, 
+        struct sockaddr_in * addr,
+        unsigned char * buf,  int len) {
+    struct msghdr msg;
+    struct iovec iov;
+    mm_segment_t oldfs;
+    int size = 0;
+
+         
+    if (sock->sk == NULL) {
+       return 0;
+    }
+
+    iov.iov_base = buf;
+    iov.iov_len = len;
+
+    msg.msg_flags = 0;
+    msg.msg_name = addr;
+    msg.msg_namelen = sizeof(struct sockaddr_in);
+    msg.msg_control = NULL;
+    msg.msg_controllen = 0;
+    msg.msg_iov = &iov;
+    msg.msg_iovlen = 1;
+    msg.msg_control = NULL;
+
+    oldfs = get_fs();
+    set_fs(KERNEL_DS);
+    size = sock_sendmsg(sock, &msg, len);
+    set_fs(oldfs);
+
+    return size;
+}
+
+
+
+static int 
+_udp_recv(struct socket * sock, 
+        struct sockaddr_in * addr,
+        unsigned char * buf, int len) {
+    struct msghdr msg;
+    struct iovec iov;
+    mm_segment_t oldfs;
+    int size = 0;
+    
+    if (sock->sk == NULL) {
+       return 0;
+    }
+
+    iov.iov_base = buf;
+    iov.iov_len = len;
+    
+    msg.msg_flags = 0;
+    msg.msg_name = addr;
+    msg.msg_namelen = sizeof(struct sockaddr_in);
+    msg.msg_control = NULL;
+    msg.msg_controllen = 0;
+    msg.msg_iov = &iov;
+    msg.msg_iovlen = 1;
+    msg.msg_control = NULL;
+    
+    oldfs = get_fs();
+    set_fs(KERNEL_DS);
+    size = sock_recvmsg(sock, &msg, len, msg.msg_flags);
+       
+    set_fs(oldfs);
+    
+    return size;
+}
+
+/* send packets to VNET core */
+static int 
+send_to_palacios(unsigned char * buf, 
+                int len,
+                int link_id){
+    struct v3_vnet_pkt pkt;
+    pkt.size = len;
+    pkt.src_type = LINK_EDGE;
+    pkt.src_id = link_id;
+    memcpy(pkt.header, buf, ETHERNET_HEADER_LEN);
+    pkt.data = buf;
+
+    if(net_debug >= 2){
+       printk("VNET Lnx Bridge: send pkt to VNET core (size: %d, src_id: %d, src_type: %d)\n", 
+                       pkt.size,  pkt.src_id, pkt.src_type);
+       if(net_debug >= 4){
+           print_hex_dump(NULL, "pkt_data: ", 0, 20, 20, pkt.data, pkt.size, 0);
+       }
+    }
+
+    vnet_brg_s.stats.pkt_to_vmm ++;
+
+    return v3_vnet_send_pkt(&pkt, NULL, 1);
+}
+
+
+/* send packet to extern network */
+static int 
+bridge_send_pkt(struct v3_vm_info * vm, 
+               struct v3_vnet_pkt * pkt, 
+               void * private_data) {
+    struct vnet_link * link;
+
+    if(net_debug >= 2){
+       printk("VNET Lnx Host Bridge: packet received from VNET Core ... pkt size: %d, link: %d\n",
+                       pkt->size,
+                       pkt->dst_id);
+       if(net_debug >= 4){
+           print_hex_dump(NULL, "pkt_data: ", 0, 20, 20, pkt->data, pkt->size, 0);
+       }
+    }
+
+    vnet_brg_s.stats.pkt_from_vmm ++;
+
+    link = _link_by_idx(pkt->dst_id);
+    if (link != NULL) {
+       switch(link->sock_proto){
+           case UDP:
+               _udp_send(link->sock, &(link->sock_addr), pkt->data, pkt->size);
+               vnet_brg_s.stats.pkt_to_phy ++;
+               break;
+           case TCP:
+               vnet_brg_s.stats.pkt_to_phy ++;
+               break;  
+
+           default:
+               printk("VNET Server: Invalid Link Protocol\n");
+               vnet_brg_s.stats.pkt_drop_vmm ++;
+       }
+       link->stats.tx_bytes += pkt->size;
+       link->stats.tx_pkts ++;
+    } else {
+       printk("VNET Bridge Linux Host: wrong dst link, idx: %d, discards the packet\n", pkt->dst_id);
+       vnet_brg_s.stats.pkt_drop_vmm ++;
+    }
+
+    return 0;
+}
+
+
+static int init_vnet_serv(void) {
+    int protocol;
+    int err;
+
+    switch(vnet_brg_s.serv_proto){
+       case UDP:
+           protocol = IPPROTO_UDP;
+           break;
+       case TCP:
+           protocol = IPPROTO_TCP;
+           break;
+
+       default:
+           printk("Unsupported VNET Server Protocol\n");
+           return -1;
+    }
+        
+    if ((err = sock_create(AF_INET, SOCK_DGRAM, protocol, &vnet_brg_s.serv_sock)) < 0) {
+       printk("Could not create VNET server socket, error: %d\n", err);
+       return -1;
+    }
+
+    memset(&vnet_brg_s.serv_addr, 0, sizeof(struct sockaddr));
+
+    vnet_brg_s.serv_addr.sin_family = AF_INET;
+    vnet_brg_s.serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
+    vnet_brg_s.serv_addr.sin_port = htons(VNET_SERVER_PORT);
+
+    if ((err = vnet_brg_s.serv_sock->ops->bind(vnet_brg_s.serv_sock, (struct sockaddr *)&(vnet_brg_s.serv_addr), sizeof(struct sockaddr))) < 0) {
+       printk("Could not bind VNET server socket to port %d, error: %d\n", VNET_SERVER_PORT, err);
+       return -1;
+    }
+
+    printk("VNET server bind to port: %d\n", VNET_SERVER_PORT);
+
+    if(vnet_brg_s.serv_proto == TCP){
+       if((err = vnet_brg_s.serv_sock->ops->listen(vnet_brg_s.serv_sock, 32)) < 0){
+           printk("VNET Server error listening on port %d, error %d\n", VNET_SERVER_PORT, err);
+           return -1;
+       }
+    }
+
+    return 0;
+}
+
+static int _udp_server(void * arg) {
+    unsigned char * pkt;
+    struct sockaddr_in pkt_addr;
+    struct vnet_link * link = NULL;
+    int len;
+
+    printk("Palacios VNET Bridge: UDP receiving server ..... \n");
+
+    pkt = kmalloc(MAX_PACKET_LEN, GFP_KERNEL);
+    while (!kthread_should_stop()) {
+       
+       len = _udp_recv(vnet_brg_s.serv_sock, &pkt_addr, pkt, MAX_PACKET_LEN); 
+       if(len < 0) {
+           printk("Receive error: Could not get packet, error %d\n", len);
+           continue;
+       }
+
+       link = _link_by_ip(pkt_addr.sin_addr.s_addr);
+       if (link == NULL){
+           printk("VNET Server: No VNET Link match the src IP\n");
+           vnet_brg_s.stats.pkt_drop_phy ++;
+           continue;
+       }
+       
+       vnet_brg_s.stats.pkt_from_phy ++;
+       link->stats.rx_bytes += len;
+       link->stats.rx_pkts ++;
+
+       send_to_palacios(pkt, len, link->idx);
+    }
+
+    kfree(pkt);
+
+    return 0;
+}
+
+
+static int _rx_server(void * arg) {
+    
+    if(vnet_brg_s.serv_proto == UDP){
+       _udp_server(NULL);
+    }else if(vnet_brg_s.serv_proto == TCP) {
+       //accept new connection
+       //use select to receive pkt from physical network
+       //or create new kthread to handle each connection?
+    }else {
+       printk ("VNET Server: Unsupported Protocol\n");
+       return -1;
+    }
+
+    return 0;
+}
+
+static inline unsigned int hash_fn(addr_t hdr_ptr) {    
+    return vnet_hash_buffer((uint8_t *)hdr_ptr, sizeof(uint32_t));
+}
+
+static inline int hash_eq(addr_t key1, addr_t key2) {  
+    return (memcmp((uint8_t *)key1, (uint8_t *)key2, sizeof(uint32_t)) == 0);
+}
+
+
+int vnet_bridge_init(void) {
+    struct v3_vnet_bridge_ops bridge_ops;
+
+    if(vnet_brg_s.status != 0) {
+       return -1;
+    }  
+    vnet_brg_s.status = 1;     
+       
+    memset(&vnet_brg_s, 0, sizeof(struct vnet_brg_state));
+
+    INIT_LIST_HEAD(&(vnet_brg_s.link_list));
+    spin_lock_init(&(vnet_brg_s.lock));
+
+    vnet_brg_s.serv_proto = UDP;
+
+    vnet_brg_s.ip2link = vnet_create_htable(10, hash_fn, hash_eq);
+    if(vnet_brg_s.ip2link == NULL){
+       printk("Failure to initiate VNET link hashtable\n");
+       return -1;
+    }
+       
+    if(init_vnet_serv() < 0){
+       printk("Failure to initiate VNET server\n");
+       return -1;
+    }
+
+    vnet_brg_s.serv_thread = kthread_run(_rx_server, NULL, "vnet-server");
+
+    bridge_ops.input = bridge_send_pkt;
+    bridge_ops.poll = NULL;
+       
+    if( v3_vnet_add_bridge(NULL, &bridge_ops, HOST_LNX_BRIDGE, NULL) < 0){
+       printk("VNET LNX Bridge: Fails to register bridge to VNET core");
+    }
+
+    printk("VNET Linux Bridge initiated\n");
+
+    return 0;
+}
+
+
+void vnet_bridge_deinit(void){
+
+    v3_vnet_del_bridge(HOST_LNX_BRIDGE);
+
+    kthread_stop(vnet_brg_s.serv_thread);
+    vnet_brg_s.serv_sock->ops->release(vnet_brg_s.serv_sock);
+
+    deinit_links_list();
+
+    vnet_free_htable(vnet_brg_s.ip2link, 0, 0);
+
+    vnet_brg_s.status = 0;
+}
+
+
similarity index 53%
rename from linux_module/palacios-vnet-bridge.c
rename to linux_module/palacios-vnet-ctrl.c
index f4a4151..f0bbac5 100644 (file)
@@ -1,5 +1,5 @@
 /* 
-   Palacios VNET Host Bridge
+   Palacios VNET Control Module
    (c) Lei Xia, 2010
  */
 #include <linux/spinlock.h>
 
 #define VNET_SERVER_PORT 9000
 
-struct palacios_vnet_route {
+struct vnet_route_iter {
     struct v3_vnet_route route;
-
-    int route_idx;
+    uint32_t idx;
 
     struct list_head node;
 };
 
-typedef enum {UDP, TCP, RAW, NONE} vnet_bridge_proto_t;
 
-struct vnet_link {
+struct vnet_link_iter {
     uint32_t dst_ip;
     uint16_t dst_port;
-    
-    struct socket * sock;
-    struct sockaddr_in sock_addr;
-    vnet_bridge_proto_t sock_proto;
-
-    unsigned int pkt_rx, pkt_tx;
-    uint64_t bytes_rx, bytes_tx;
-
-    int link_idx;
+    vnet_brg_proto_t proto;
+    uint32_t idx;
 
     struct list_head node;
 };
 
 
-struct palacios_vnet_state {
-    uint32_t num_routes;
-    uint32_t num_links; 
-
+struct vnet_ctrl_state {
     uint8_t status;
 
+    uint32_t num_links;
+    uint32_t num_routes;
+       
     struct list_head route_list;
-    struct list_head link_list;
-
-    struct hashtable *ip2link; /* map IP to its Link */
+    struct list_head link_iter_list;
 
     spinlock_t lock;
 
-    struct socket * serv_sock;
-    struct sockaddr_in serv_addr;
-    vnet_bridge_proto_t serv_proto;
-
-    /* Socket Receiving Thread */
-    struct task_struct * serv_thread;
-
-    unsigned int pkt_from_vmm, pkt_to_vmm, pkt_drop_vmm;
-    unsigned int pkt_from_phy, pkt_to_phy, pkt_drop_phy;
+    struct proc_dir_entry * vnet_proc_root;
 };
 
 
-static struct palacios_vnet_state vnet_state;
-
-
-static inline struct vnet_link * link_by_ip(uint32_t ip) {
-    return (struct vnet_link *)vnet_htable_search(vnet_state.ip2link, (addr_t)&ip);
-}
-
-static inline struct vnet_link * link_by_idx(int idx) {
-    struct vnet_link * link = NULL;
-
-    list_for_each_entry(link, &(vnet_state.link_list), node) {
-
-       if (link->link_idx == idx) {
-           return link;
-       }
-    }
-    return NULL;
-}
-
-static inline struct palacios_vnet_route * route_by_idx(int idx) {
-    struct palacios_vnet_route * route = NULL;
-
-    list_for_each_entry(route, &(vnet_state.route_list), node) {
-
-       if (route->route_idx == idx) {
-           return route;
-       }
-    }
-
-    return NULL;
-}
+static struct vnet_ctrl_state vnet_ctrl_s;
 
 
 static int parse_mac_str(char * str, uint8_t * qual, uint8_t * mac) {
@@ -178,19 +129,35 @@ static int str2mac(char * str, uint8_t * mac){
 }
 
 
-/* Format:
-  * add src-MAC dst-MAC dst-TYPE [dst-ID] src-TYPE [src-ID]
-  *
-  * src-MAC = dst-MAC = not-MAC|any|none|MAC 
-  * dst-TYPE = edge|interface 
-  * src-TYPE = edge|interface|any
-  * dst-ID = src-ID = IP|MAC
-  * MAC=xx:xx:xx:xx:xx:xx
-  * IP = xxx.xxx.xxx.xxx
-  */
+static inline struct vnet_link_iter * link_by_ip(uint32_t ip) {
+    struct vnet_link_iter * link = NULL;
+
+    list_for_each_entry(link, &(vnet_ctrl_s.link_iter_list), node) {
+
+       if (link->dst_ip == ip) {
+           return link;
+       }
+    }
+       
+    return NULL;
+}
+
+static inline struct vnet_link_iter * link_by_idx(int idx) {
+    struct vnet_link_iter * link = NULL;
+
+    list_for_each_entry(link, &(vnet_ctrl_s.link_iter_list), node) {
+       if (link->idx == idx) {
+           return link;
+       }
+    }
+       
+    return NULL;
+}
+
+
 static int parse_route_str(char * str, struct v3_vnet_route * route) {
     char * token = NULL;
-    struct vnet_link *link = NULL;
+    struct vnet_link_iter * link = NULL;
 
     // src MAC
     token = strsep(&str, " ");
@@ -241,13 +208,13 @@ static int parse_route_str(char * str, struct v3_vnet_route * route) {
 
        link = link_by_ip(link_ip);
        if (link != NULL){
-           route->dst_id = link->link_idx;
+           route->dst_id = link->idx;
        }else{
            printk("can not find dst link %s\n", token);
            return -1;
        }
 
-       printk("link_ip = %d, link_id = %d\n", link_ip, link->link_idx);        
+       printk("link_ip = %d, link_id = %d\n", link_ip, link->idx);     
     } else if (route->dst_type == LINK_INTERFACE) {
        uint8_t mac[ETH_ALEN];
        
@@ -308,7 +275,7 @@ static int parse_route_str(char * str, struct v3_vnet_route * route) {
 
        link = link_by_ip(src_ip);
        if (link != NULL){
-           route->src_id = link->link_idx;
+           route->src_id = link->idx;
        }else{
            printk("can not find src link %s\n", token);
            return -1;
@@ -335,19 +302,15 @@ static int parse_route_str(char * str, struct v3_vnet_route * route) {
 }
 
 
-
-
 static void * route_seq_start(struct seq_file * s, loff_t * pos) {
-    struct palacios_vnet_route * route_iter = NULL;
+    struct vnet_route_iter * route_iter = NULL;
     loff_t i = 0;
 
-
-    if (*pos >= vnet_state.num_routes) {
+    if (*pos >= vnet_ctrl_s.num_routes) {
        return NULL;
     }
 
-    list_for_each_entry(route_iter, &(vnet_state.route_list), node) {
-
+    list_for_each_entry(route_iter, &(vnet_ctrl_s.route_list), node) {
        if (i == *pos) {
            break;
        }
@@ -359,35 +322,13 @@ static void * route_seq_start(struct seq_file * s, loff_t * pos) {
 }
 
 
-static void * link_seq_start(struct seq_file * s, loff_t * pos) {
-    struct vnet_link * link_iter = NULL;
-    loff_t i = 0;
-
-    if (*pos >= vnet_state.num_links) {
-       return NULL;
-    }
-
-    list_for_each_entry(link_iter, &(vnet_state.link_list), node) {
-
-       if (i == *pos) {
-           break;
-       }
-
-       i++;
-    }
-
-    return link_iter;
-}
-
-
-
 static void * route_seq_next(struct seq_file * s, void * v, loff_t * pos) {
-    struct palacios_vnet_route * route_iter = NULL;
+    struct vnet_route_iter * route_iter = NULL;
 
-    route_iter = list_entry(((struct palacios_vnet_route *)v)->node.next, struct palacios_vnet_route, node);
+    route_iter = list_entry(((struct vnet_route_iter *)v)->node.next, struct vnet_route_iter, node);
 
     // Check if the list has looped
-    if (&(route_iter->node) == &(vnet_state.route_list)) {
+    if (&(route_iter->node) == &(vnet_ctrl_s.route_list)) {
        return NULL;
     }
 
@@ -396,40 +337,35 @@ static void * route_seq_next(struct seq_file * s, void * v, loff_t * pos) {
     return route_iter;
 }
 
+static void route_seq_stop(struct seq_file * s, void * v) {
 
-static void * link_seq_next(struct seq_file * s, void * v, loff_t * pos) {
-    struct vnet_link * link_iter = NULL;
+    return;
+}
 
-    link_iter = list_entry(((struct vnet_link *)v)->node.next, struct vnet_link, node);
+static void * link_seq_start(struct seq_file * s, loff_t * pos) {
+    struct vnet_link_iter * link_iter = NULL;
+    loff_t i = 0;
 
-    // Check if the list has looped
-    if (&(link_iter->node) == &(vnet_state.link_list)) {
+    if (*pos >= vnet_ctrl_s.num_links) {
        return NULL;
     }
 
-    *pos += 1;
-
-    return link_iter;
-}
-
-
-static void route_seq_stop(struct seq_file * s, void * v) {
-
-    return;
-}
-
+    list_for_each_entry(link_iter, &(vnet_ctrl_s.link_iter_list), node) {
+       if (i == *pos) {
+           break;
+       }
 
-static void link_seq_stop(struct seq_file * s, void * v) {
+       i++;
+    }
 
-    return;
+    return link_iter;
 }
 
 static int route_seq_show(struct seq_file * s, void * v) {
-    struct palacios_vnet_route * route_iter = v;
+    struct vnet_route_iter * route_iter = v;
     struct v3_vnet_route * route = &(route_iter->route);
 
-    seq_printf(s, "%d:\t", route_iter->route_idx);
+    seq_printf(s, "%d:\t", route_iter->idx);
 
     seq_printf(s, "\nSrc:\t");
     switch (route->src_mac_qual) {
@@ -474,7 +410,7 @@ static int route_seq_show(struct seq_file * s, void * v) {
     seq_printf(s, "\nDst-Type:\t");
     switch (route->dst_type) {
        case LINK_EDGE: {
-           struct vnet_link * link = (struct vnet_link *)link_by_idx(route->dst_id);
+           struct vnet_link_iter * link = (struct vnet_link_iter *)link_by_idx(route->dst_id);
            seq_printf(s, "EDGE %pI4", &link->dst_ip);
            break;
        }
@@ -491,7 +427,7 @@ static int route_seq_show(struct seq_file * s, void * v) {
     seq_printf(s, "\nSrc-Type:\t");
     switch (route->src_type) {
        case LINK_EDGE: {
-           struct vnet_link * link = (struct vnet_link *)link_by_idx(route->src_id);
+           struct vnet_link_iter * link = (struct vnet_link_iter *)link_by_idx(route->src_id);
            seq_printf(s, "EDGE %pI4", &link->dst_ip);
            break;
        }
@@ -507,24 +443,45 @@ static int route_seq_show(struct seq_file * s, void * v) {
            break;
     }
 
-
     seq_printf(s, "\n");
 
     return 0;
 }
 
+static void * link_seq_next(struct seq_file * s, void * v, loff_t * pos) {
+    struct vnet_link_iter * link_iter = NULL;
+
+    link_iter = list_entry(((struct vnet_link_iter *)v)->node.next, struct vnet_link_iter, node);
+
+    // Check if the list has looped
+    if (&(link_iter->node) == &(vnet_ctrl_s.link_iter_list)) {
+       return NULL;
+    }
+
+    *pos += 1;
+
+    return link_iter;
+}
+
+static void link_seq_stop(struct seq_file * s, void * v) {
+
+    return;
+}
 
 static int link_seq_show(struct seq_file * s, void * v) {
-    struct vnet_link * link_iter = v;
+    struct vnet_link_iter * link_iter = v;
+    struct nic_statistics stats;
+
+    vnet_brg_link_stats(link_iter->idx, &stats);
 
-    seq_printf(s, "%d:\t%pI4\t%d\n\t\tReceived Pkts: %d, Received Bytes %lld\n\t\tSent Pkts: %d, Sent Bytes: %lld\n\n", 
-              link_iter->link_idx,
+    seq_printf(s, "%d:\t%pI4\t%d\n\t\tReceived Pkts: %lld, Received Bytes %lld\n\t\tSent Pkts: %lld, Sent Bytes: %lld\n\n", 
+              link_iter->idx,
               &link_iter->dst_ip,
               link_iter->dst_port,
-              link_iter->pkt_rx,
-              link_iter->bytes_rx,
-              link_iter->pkt_tx,
-              link_iter->bytes_tx);
+              stats.rx_pkts,
+              stats.rx_bytes,
+              stats.tx_pkts,
+              stats.tx_bytes);
 
     return 0;
 }
@@ -555,21 +512,55 @@ static int link_open(struct inode * inode, struct file * file) {
     return seq_open(file, &link_seq_ops);
 }
 
-static int inject_route(struct palacios_vnet_route * route) {
-    unsigned long flags;
 
-    v3_vnet_add_route(route->route);
 
-    spin_lock_irqsave(&(vnet_state.lock), flags);
-    list_add(&(route->node), &(vnet_state.route_list));
-    route->route_idx = vnet_state.num_routes++;
-    spin_unlock_irqrestore(&(vnet_state.lock), flags);
+static int inject_route(struct vnet_route_iter * route) {
+    unsigned long flags;
+    
+    route->idx = v3_vnet_add_route(route->route);
+
+    spin_lock_irqsave(&(vnet_ctrl_s.lock), flags);
+    list_add(&(route->node), &(vnet_ctrl_s.route_list));
+    vnet_ctrl_s.num_routes ++;
+    spin_unlock_irqrestore(&(vnet_ctrl_s.lock), flags);
 
-    printk("Palacios-vnet: One route added to VNET core\n");
+    printk("VNET Control: One route added to VNET core\n");
 
     return 0;
 }
 
+
+static void delete_route(struct vnet_route_iter * route) {
+    unsigned long flags;
+
+    v3_vnet_del_route(route->idx);
+
+    spin_lock_irqsave(&(vnet_ctrl_s.lock), flags);
+    list_del(&(route->node));
+    vnet_ctrl_s.num_routes --;
+    spin_unlock_irqrestore(&(vnet_ctrl_s.lock), flags);
+
+    printk("VNET Control: Route %d deleted from VNET\n", route->idx);
+
+    kfree(route);
+    route = NULL;
+}
+
+
+/* Format:
+  * add src-MAC dst-MAC dst-TYPE [dst-ID] src-TYPE [src-ID]
+  *
+  * src-MAC = dst-MAC = not-MAC|any|none|MAC 
+  * dst-TYPE = edge|interface 
+  * src-TYPE = edge|interface|any
+  * dst-ID = src-ID = IP|MAC
+  * MAC=xx:xx:xx:xx:xx:xx
+  * IP = xxx.xxx.xxx.xxx
+  *
+  *
+  * del route-idx
+  *
+  */
 static ssize_t 
 route_write(struct file * file, 
            const char * buf, 
@@ -599,14 +590,14 @@ route_write(struct file * file,
        }
        
        if (strnicmp("ADD", token, strlen("ADD")) == 0) {
-           struct palacios_vnet_route * new_route = NULL;
-           new_route = kmalloc(sizeof(struct palacios_vnet_route), GFP_KERNEL);
+           struct vnet_route_iter * new_route = NULL;
+           new_route = kmalloc(sizeof(struct vnet_route_iter), GFP_KERNEL);
            
            if (!new_route) {
                return -ENOMEM;
            }
            
-           memset(new_route, 0, sizeof(struct palacios_vnet_route));
+           memset(new_route, 0, sizeof(struct vnet_route_iter));
            
            if (parse_route_str(buf_iter, &(new_route->route)) == -1) {
                kfree(new_route);
@@ -614,10 +605,26 @@ route_write(struct file * file,
            }
            
            if (inject_route(new_route) != 0) {
+               kfree(new_route);
                return -EFAULT;
            }
        } else if (strnicmp("DEL", token, strlen("DEL")) == 0) {
-           printk("I should delete the route here\n");
+           char * idx_str = NULL;
+           uint32_t d_idx;
+           
+           idx_str = strsep(&buf_iter, " ");
+           
+           if (!idx_str) {
+               printk("Missing route idx in DEL Route command\n");
+               return -EFAULT;
+           }
+
+           d_idx = simple_strtoul(idx_str, &idx_str, 10);
+
+           v3_vnet_del_route(d_idx);
+               
+           printk("VNET Control: One route deleted\n");                
+
        } else {
            printk("Invalid Route command string\n");
        }
@@ -626,62 +633,40 @@ route_write(struct file * file,
     return size;
 }
 
-static int create_link(struct vnet_link * link) {
-    int err;
+
+static void delete_link(struct vnet_link_iter * link){
     unsigned long flags;
-    int protocol;
 
-    switch(link->sock_proto){
-       case UDP:
-           protocol = IPPROTO_UDP;
-           break;
-       case TCP:
-           protocol = IPPROTO_TCP;
-           break;
+    vnet_brg_delete_link(link->idx);
 
-       default:
-           printk("Unsupported VNET Server Protocol\n");
-           return -1;
-    }
-   
-    if ((err = sock_create(AF_INET, SOCK_DGRAM, protocol, &link->sock)) < 0) {
-       printk("Could not create socket for VNET Link, error %d\n", err);
-       return -1;
-    }
+    spin_lock_irqsave(&(vnet_ctrl_s.lock), flags);
+    list_del(&(link->node));
+    vnet_ctrl_s.num_links --;
+    spin_unlock_irqrestore(&(vnet_ctrl_s.lock), flags);
 
-    memset(&link->sock_addr, 0, sizeof(struct sockaddr));
+    kfree(link);
+    link = NULL;
+}
 
-    link->sock_addr.sin_family = AF_INET;
-    link->sock_addr.sin_addr.s_addr = link->dst_ip;
-    link->sock_addr.sin_port = htons(link->dst_port);
 
-    if ((err = link->sock->ops->connect(link->sock, (struct sockaddr *)&(link->sock_addr), sizeof(struct sockaddr), 0) < 0)) {
-       printk("Could not connect to remote VNET Server, error %d\n", err);
-       return -1;
-    }
+static void deinit_links_list(void){
+    struct vnet_link_iter * link;
 
-    // We use the file pointer because we are in the kernel
-    // This is only used to assigned File Descriptors for user space, so it is available here
-    // link->sock->file = link;
-
-    spin_lock_irqsave(&(vnet_state.lock), flags);
-    list_add(&(link->node), &(vnet_state.link_list));
-    link->link_idx = vnet_state.num_links++;
-    vnet_htable_insert(vnet_state.ip2link, (addr_t)&(link->dst_ip), (addr_t)link);
-    spin_unlock_irqrestore(&(vnet_state.lock), flags);
+    list_for_each_entry(link, &(vnet_ctrl_s.link_iter_list), node) {
+       delete_link(link);
+    }
+}
 
-    printk("VNET Bridge: Link created, ip 0x%x, port: %d, idx: %d, link: %p, protocol: %s\n", 
-          link->dst_ip, 
-          link->dst_port, 
-          link->link_idx, 
-          link,
-          ((link->sock_proto==UDP)?"UDP":"TCP"));
+static void deinit_routes_list(void){
+   struct vnet_route_iter * route;
 
-    return 0;
+   list_for_each_entry(route, &(vnet_ctrl_s.route_list), node) {
+       delete_route(route);
+   }
 }
 
-
 /* ADD dst-ip 9000 [udp|tcp] */
+/* DEL link-idx */
 static ssize_t 
 link_write(struct file * file, const char * buf, size_t size, loff_t * ppos) {
     char link_buf[256];
@@ -707,9 +692,13 @@ link_write(struct file * file, const char * buf, size_t size, loff_t * ppos) {
        }
        
        if (strnicmp("ADD", token, strlen("ADD")) == 0) {
-           struct vnet_link * new_link = NULL;
+           struct vnet_link_iter * link = NULL;
            char * ip_str = NULL;
-           uint32_t ip;
+           uint32_t d_ip;
+           uint16_t d_port;
+           vnet_brg_proto_t d_proto;
+           int link_idx;
+           unsigned long flags;
            
            ip_str = strsep(&link_iter, " ");
            
@@ -718,32 +707,48 @@ link_write(struct file * file, const char * buf, size_t size, loff_t * ppos) {
                return -EFAULT;
            }
            
-           if (in4_pton(ip_str, strlen(ip_str), (uint8_t *)&(ip), '\0', NULL) != 1) {
+           if (in4_pton(ip_str, strlen(ip_str), (uint8_t *)&(d_ip), '\0', NULL) != 1) {
                printk("Invalid Dst IP address (%s)\n", ip_str);
                return -EFAULT;
            }
 
-           new_link = kmalloc(sizeof(struct vnet_link), GFP_KERNEL);
-           if (!new_link) {
-               return -ENOMEM;
+           d_port = simple_strtol(link_iter, &link_iter, 10);
+           d_proto = UDP;
+
+           link_idx = vnet_brg_add_link(d_ip, d_port, d_proto);
+           if(link_idx < 0){
+               printk("VNET Control: Failed to create link\n");
+               return -EFAULT;
            }
-       
-           memset(new_link, 0, sizeof(struct vnet_link));
 
-           new_link->dst_ip = ip;
-           new_link->dst_port = simple_strtol(link_iter, &link_iter, 10);
+           link = kmalloc(sizeof(struct vnet_link_iter), GFP_KERNEL);
+           memset(link, 0, sizeof(struct vnet_link_iter));
 
-           //TODO: Parse UDP|TCP
-           new_link->sock_proto = UDP;
+           link->dst_ip = d_ip;
+           link->dst_port = d_port;
+           link->proto = d_proto;
+           link->idx = link_idx;
+
+           spin_lock_irqsave(&(vnet_ctrl_s.lock), flags);
+           list_add(&(link->node), &(vnet_ctrl_s.link_iter_list));
+           vnet_ctrl_s.num_links ++;
+           spin_unlock_irqrestore(&(vnet_ctrl_s.lock), flags);
+       } else if (strnicmp("DEL", token, strlen("DEL")) == 0) {
+           char * idx_str = NULL;
+           uint32_t d_idx;
            
-           if (create_link(new_link) != 0) {
-               printk("Could not create link\n");
-               kfree(new_link);
+           idx_str = strsep(&link_iter, " ");
+           
+           if (!idx_str) {
+               printk("Missing link idx in DEL Link command\n");
                return -EFAULT;
            }
 
-       } else if (strnicmp("DEL", token, strlen("DEL")) == 0) {
-           printk("Link deletion not supported\n");
+           d_idx = simple_strtoul(idx_str, &idx_str, 10);
+
+           vnet_brg_delete_link(d_idx);
+               
+           printk("VNET Control: One link deleted\n");         
        } else {
            printk("Invalid Link command string\n");
        }
@@ -775,26 +780,26 @@ static struct file_operations link_fops = {
 
 static ssize_t 
 debug_write(struct file * file, const char * buf, size_t size, loff_t * ppos) {
-    char link_buf[32];
-    char * link_iter = NULL;
-    char * line_str = link_buf;
+    char in_buf[32];
+    char * in_iter = NULL;
+    char * line_str = in_buf;
     int level = -1; 
 
     if (size >= 32) {
        return -EFAULT;
     }
 
-    if (copy_from_user(link_buf, buf, size)) {
+    if (copy_from_user(in_buf, buf, size)) {
        return -EFAULT;
     }
 
-    link_iter = strsep(&line_str, "\r\n");
-    level = simple_strtol(link_iter, &link_iter, 10);
+    in_iter = strsep(&line_str, "\r\n");
+    level = simple_strtol(in_iter, &in_iter, 10);
 
-    printk("Set VNET Debug level to %d\n", level);
+    printk("VNET Control: Set VNET Debug level to %d\n", level);
 
     if(level >= 0){
-       vnet_debug = level;
+       net_debug = level;
     }
 
     return size;
@@ -802,7 +807,7 @@ debug_write(struct file * file, const char * buf, size_t size, loff_t * ppos) {
 
 
 static int debug_show(struct seq_file * file, void * v){
-    seq_printf(file, "Current VNET Debug Level: %d\n", vnet_debug);
+    seq_printf(file, "Current NET Debug Level: %d\n", net_debug);
        
     return 0;
 }
@@ -822,6 +827,7 @@ static struct file_operations debug_fops = {
 
 static int stat_show(struct seq_file * file, void * v){
     struct vnet_stat stats;
+    struct vnet_brg_stats brg_stats;
 
     v3_vnet_stat(&stats);
 
@@ -831,14 +837,15 @@ static int stat_show(struct seq_file * file, void * v){
     seq_printf(file, "\tTransmitted Packets: %d\n", stats.tx_pkts);
     seq_printf(file, "\tTransmitted Bytes: %lld\n", stats.tx_bytes);
 
-
+    vnet_brg_stats(&brg_stats);
+   
     seq_printf(file, "\nVNET Bridge Server\n");
-    seq_printf(file, "\tReceived From VMM: %d\n", vnet_state.pkt_from_vmm);
-    seq_printf(file, "\tSent To VMM: %d\n", vnet_state.pkt_to_vmm);
-    seq_printf(file, "\tDropped From VMM: %d\n", vnet_state.pkt_drop_vmm);
-    seq_printf(file, "\tReceived From Extern Network: %d\n", vnet_state.pkt_from_phy);
-    seq_printf(file, "\tSent To Extern Network: %d\n", vnet_state.pkt_to_phy);
-    seq_printf(file, "\tDropped From Extern Network: %d\n", vnet_state.pkt_drop_phy);
+    seq_printf(file, "\tReceived From VMM: %lld\n", brg_stats.pkt_from_vmm);
+    seq_printf(file, "\tSent To VMM: %lld\n", brg_stats.pkt_to_vmm);
+    seq_printf(file, "\tDropped From VMM: %lld\n", brg_stats.pkt_drop_vmm);
+    seq_printf(file, "\tReceived From Extern Network: %lld\n", brg_stats.pkt_from_phy);
+    seq_printf(file, "\tSent To Extern Network: %lld\n", brg_stats.pkt_to_phy);
+    seq_printf(file, "\tDropped From Extern Network: %lld\n", brg_stats.pkt_drop_phy);
 
     return 0;
 }
@@ -904,300 +911,51 @@ static int init_proc_files(void) {
        return -1;
     }
     debug_entry->proc_fops = &debug_fops;
-       
-
-    return 0;
-}
-
-
-
-static int 
-udp_send(struct socket * sock, 
-        struct sockaddr_in * addr,
-        unsigned char * buf,  int len) {
-    struct msghdr msg;
-    struct iovec iov;
-    mm_segment_t oldfs;
-    int size = 0;
-
-         
-    if (sock->sk == NULL) {
-       return 0;
-    }
-
-    iov.iov_base = buf;
-    iov.iov_len = len;
-
-    msg.msg_flags = 0;
-    msg.msg_name = addr;
-    msg.msg_namelen = sizeof(struct sockaddr_in);
-    msg.msg_control = NULL;
-    msg.msg_controllen = 0;
-    msg.msg_iov = &iov;
-    msg.msg_iovlen = 1;
-    msg.msg_control = NULL;
 
-    oldfs = get_fs();
-    set_fs(KERNEL_DS);
-    size = sock_sendmsg(sock, &msg, len);
-    set_fs(oldfs);
-
-    return size;
-}
-
-
-
-static int 
-udp_recv(struct socket * sock, 
-        struct sockaddr_in * addr,
-        unsigned char * buf, int len) {
-    struct msghdr msg;
-    struct iovec iov;
-    mm_segment_t oldfs;
-    int size = 0;
-    
-    if (sock->sk == NULL) {
-       return 0;
-    }
-
-    iov.iov_base = buf;
-    iov.iov_len = len;
-    
-    msg.msg_flags = 0;
-    msg.msg_name = addr;
-    msg.msg_namelen = sizeof(struct sockaddr_in);
-    msg.msg_control = NULL;
-    msg.msg_controllen = 0;
-    msg.msg_iov = &iov;
-    msg.msg_iovlen = 1;
-    msg.msg_control = NULL;
-    
-    oldfs = get_fs();
-    set_fs(KERNEL_DS);
-    size = sock_recvmsg(sock, &msg, len, msg.msg_flags);
-       
-    set_fs(oldfs);
-    
-    return size;
-}
-
-/* send packets to VNET core */
-static int 
-send_to_palacios(unsigned char * buf, 
-                int len,
-                int link_id){
-    struct v3_vnet_pkt pkt;
-    pkt.size = len;
-    pkt.src_type = LINK_EDGE;
-    pkt.src_id = link_id;
-    memcpy(pkt.header, buf, ETHERNET_HEADER_LEN);
-    pkt.data = buf;
-
-    if(vnet_debug >= 2){
-       printk("VNET Lnx Bridge: send pkt to VNET core (size: %d, src_id: %d, src_type: %d)\n", 
-                       pkt.size,  pkt.src_id, pkt.src_type);
-       if(vnet_debug >= 4){
-           print_hex_dump(NULL, "pkt_data: ", 0, 20, 20, pkt.data, pkt.size, 0);
-       }
-    }
-
-    vnet_state.pkt_to_vmm ++;
-
-    return v3_vnet_send_pkt(&pkt, NULL, 1);
-}
-
-
-/* send packet to extern network */
-static int 
-bridge_send_pkt(struct v3_vm_info * vm, 
-               struct v3_vnet_pkt * pkt, 
-               void * private_data) {
-    struct vnet_link * link;
-
-    if(vnet_debug >= 2){
-       printk("VNET Lnx Host Bridge: packet received from VNET Core ... pkt size: %d, link: %d\n",
-                       pkt->size,
-                       pkt->dst_id);
-       if(vnet_debug >= 4){
-           print_hex_dump(NULL, "pkt_data: ", 0, 20, 20, pkt->data, pkt->size, 0);
-       }
-    }
-
-    vnet_state.pkt_from_vmm ++;
-
-    link = link_by_idx(pkt->dst_id);
-    if (link != NULL) {
-       switch(link->sock_proto){
-           case UDP:
-               udp_send(link->sock, &(link->sock_addr), pkt->data, pkt->size);
-               vnet_state.pkt_to_phy ++;
-               break;
-           case TCP:
-               vnet_state.pkt_to_phy ++;
-               break;  
-
-           default:
-               printk("VNET Server: Invalid Link Protocol\n");
-               vnet_state.pkt_drop_vmm ++;
-       }
-       link->bytes_tx += pkt->size;
-       link->pkt_tx ++;
-    } else {
-       printk("VNET Bridge Linux Host: wrong dst link, idx: %d, discards the packet\n", pkt->dst_id);
-       vnet_state.pkt_drop_vmm ++;
-    }
+    vnet_ctrl_s.vnet_proc_root = vnet_root;
 
     return 0;
 }
 
 
-static int init_vnet_serv(void) {
-    int protocol;
-    int err;
-
-    switch(vnet_state.serv_proto){
-       case UDP:
-           protocol = IPPROTO_UDP;
-           break;
-       case TCP:
-           protocol = IPPROTO_TCP;
-           break;
+static void destroy_proc_files(void) {
+    struct proc_dir_entry * vnet_root = vnet_ctrl_s.vnet_proc_root;
 
-       default:
-           printk("Unsupported VNET Server Protocol\n");
-           return -1;
-    }
-        
-    if ((err = sock_create(AF_INET, SOCK_DGRAM, protocol, &vnet_state.serv_sock)) < 0) {
-       printk("Could not create VNET server socket, error: %d\n", err);
-       return -1;
-    }
-
-    memset(&vnet_state.serv_addr, 0, sizeof(struct sockaddr));
-
-    vnet_state.serv_addr.sin_family = AF_INET;
-    vnet_state.serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
-    vnet_state.serv_addr.sin_port = htons(VNET_SERVER_PORT);
-
-    if ((err = vnet_state.serv_sock->ops->bind(vnet_state.serv_sock, (struct sockaddr *)&(vnet_state.serv_addr), sizeof(struct sockaddr))) < 0) {
-       printk("Could not bind VNET server socket to port %d, error: %d\n", VNET_SERVER_PORT, err);
-       return -1;
-    }
-
-    printk("VNET server bind to port: %d\n", VNET_SERVER_PORT);
-
-    if(vnet_state.serv_proto == TCP){
-       if((err = vnet_state.serv_sock->ops->listen(vnet_state.serv_sock, 32)) < 0){
-           printk("VNET Server error listening on port %d, error %d\n", VNET_SERVER_PORT, err);
-           return -1;
-       }
-    }
-
-    return 0;
+    remove_proc_entry("debug", vnet_root);
+    remove_proc_entry("links", vnet_root);
+    remove_proc_entry("routes", vnet_root);
+    remove_proc_entry("stats", vnet_root);
+    remove_proc_entry("vnet", NULL);   
 }
 
-static int vnet_udp_server(void * arg) {
-    unsigned char * pkt;
-    struct sockaddr_in pkt_addr;
-    struct vnet_link * link = NULL;
-    int len;
-
-    printk("Palacios VNET Bridge: UDP receiving server ..... \n");
 
-    pkt = kmalloc(MAX_PACKET_LEN, GFP_KERNEL);
-    while (!kthread_should_stop()) {
-       
-       len = udp_recv(vnet_state.serv_sock, &pkt_addr, pkt, MAX_PACKET_LEN); 
-       if(len < 0) {
-           printk("Receive error: Could not get packet, error %d\n", len);
-           continue;
-       }
-
-       link = link_by_ip(pkt_addr.sin_addr.s_addr);
-       if (link == NULL){
-           printk("VNET Server: No VNET Link match the src IP\n");
-           vnet_state.pkt_drop_phy ++;
-           continue;
-       }
-       
-       vnet_state.pkt_from_phy ++;
-       link->bytes_rx += len;
-       link->pkt_rx ++;
-
-       send_to_palacios(pkt, len, link->link_idx);
-    }
-
-    kfree(pkt);
-
-    return 0;
-}
-
-
-
-static int vnet_server(void * arg) {
-    
-    if(vnet_state.serv_proto == UDP){
-       vnet_udp_server(NULL);
-    }else if(vnet_state.serv_proto == TCP) {
-       //accept new connection
-       //use select to receive pkt from physical network
-       //or create new kthread to handle each connection?
-    }else {
-       printk ("VNET Server: Unsupported Protocol\n");
-       return -1;
-    }
-
-    return 0;
-}
-
-static inline unsigned int hash_fn(addr_t hdr_ptr) {    
-    return vnet_hash_buffer((uint8_t *)hdr_ptr, sizeof(uint32_t));
-}
-
-static inline int hash_eq(addr_t key1, addr_t key2) {  
-    return (memcmp((uint8_t *)key1, (uint8_t *)key2, sizeof(uint32_t)) == 0);
-}
-
-
-int  palacios_init_vnet(void) {
-    struct v3_vnet_bridge_ops bridge_ops;
-
-
-    if(vnet_state.status != 0) {
+int vnet_ctrl_init(void) {
+    if(vnet_ctrl_s.status != 0) {
        return -1;
     }  
-    vnet_state.status = 1;     
+    vnet_ctrl_s.status = 1;    
        
-    memset(&vnet_state, 0, sizeof(struct palacios_vnet_state));
+    memset(&vnet_ctrl_s, 0, sizeof(struct vnet_ctrl_state));
 
-    INIT_LIST_HEAD(&(vnet_state.link_list));
-    INIT_LIST_HEAD(&(vnet_state.route_list));
-    spin_lock_init(&(vnet_state.lock));
+    INIT_LIST_HEAD(&(vnet_ctrl_s.link_iter_list));
+    INIT_LIST_HEAD(&(vnet_ctrl_s.route_list));
+    spin_lock_init(&(vnet_ctrl_s.lock));
 
     init_proc_files();
-
-    vnet_state.serv_proto = UDP;
-
-    vnet_state.ip2link = vnet_create_htable(10, hash_fn, hash_eq);
-    if(vnet_state.ip2link == NULL){
-       printk("Failure to initiate VNET link hashtable\n");
-       return -1;
-    }
        
-    if(init_vnet_serv() < 0){
-       printk("Failure to initiate VNET server\n");
-       return -1;
-    }
+    printk("VNET Linux control module initiated\n");
 
-    vnet_state.serv_thread = kthread_run(vnet_server, NULL, "vnet-server");
+    return 0;
+}
 
-    bridge_ops.input = bridge_send_pkt;
-    bridge_ops.poll = NULL;
-       
-    v3_vnet_add_bridge(NULL, &bridge_ops, HOST_LNX_BRIDGE, NULL);
 
-    printk("Palacios VNET Linux Bridge initiated\n");
+void vnet_ctrl_deinit(void){
+    destroy_proc_files();
 
-    return 0;
+    deinit_links_list();
+    deinit_routes_list();
+
+    vnet_ctrl_s.status = 0;
 }
 
+
index 32f6bd6..4f3cbd5 100644 (file)
@@ -15,6 +15,7 @@
 
 #include <vnet/vnet.h>
 #include "palacios-mm.h"
+#include "palacios-vnet.h"
 
 static void host_print(const char *    fmt, ...) {
 
@@ -276,10 +277,24 @@ static struct vnet_host_hooks vnet_host_hooks = {
 
 
 
-int vnet_init( void ) {
-    printk("Host init VNET\n");
-
+int palacios_vnet_init( void ) {
     init_vnet(&vnet_host_hooks);
+       
+    vnet_bridge_init();
+    vnet_ctrl_init();
+
+    printk("V3 VNET Inited\n");
         
     return 0;
 }
+
+
+void palacios_vnet_deinit( void ) {
+    deinit_vnet();
+
+    vnet_bridge_deinit();
+    vnet_ctrl_deinit();
+
+    printk("V3 VNET Deinited\n");
+}
+
index 010b99a..56ac9f1 100644 (file)
@@ -1,12 +1,38 @@
 /*
- * Palacios VNET Host Bridge
+ * Palacios VNET Host Header
  * (c) Lei Xia, 2010
  */
 
-#ifndef __PALACIOS_VNET_BRIDGE_H__
-#define __PALACIOS_VNET_BRIDGE_H__
+#ifndef __PALACIOS_VNET_H__
+#define __PALACIOS_VNET_H__
+
+#include <vnet/vnet.h>
+
+int  palacios_vnet_init(void);
+void palacios_vnet_deinit(void);
+
+typedef enum {UDP, TCP, RAW, NONE} vnet_brg_proto_t;
+
+struct vnet_brg_stats{
+    uint64_t pkt_from_vmm;
+    uint64_t pkt_to_vmm;
+    uint64_t pkt_drop_vmm;
+    uint64_t pkt_from_phy;
+    uint64_t pkt_to_phy;
+    uint64_t pkt_drop_phy;
+};
+
+void vnet_brg_delete_link(uint32_t idx);
+uint32_t vnet_brg_add_link(uint32_t ip, uint16_t port, vnet_brg_proto_t proto);
+int vnet_brg_link_stats(uint32_t link_idx, struct nic_statistics * stats);
+int vnet_brg_stats(struct vnet_brg_stats * stats);
+int  vnet_bridge_init(void);
+void vnet_bridge_deinit(void);
+
+
+int vnet_ctrl_init(void);
+void vnet_ctrl_deinit(void);
 
-int  palacios_init_vnet(void);
 
 #endif
 
index ca3034b..1fd00ac 100644 (file)
@@ -20,6 +20,8 @@
 #ifndef __ETHERNET_H__
 #define __ETHERNET_H__
 
+#include <palacios/vmm.h>
+
 #define ETHERNET_HEADER_LEN 14
 #define ETHERNET_MTU   1500
 #define ETHERNET_PACKET_LEN (ETHERNET_HEADER_LEN + ETHERNET_MTU)
 
 #define MAX_PACKET_LEN (ETHERNET_HEADER_LEN + MAX_MTU)
 
+#ifdef V3_CONFIG_VNET
+extern int net_debug;
+#endif
 
-extern int vnet_debug;
+struct nic_statistics {
+    uint64_t tx_pkts;
+    uint64_t tx_bytes;
+    uint64_t tx_dropped;
+
+    uint64_t rx_pkts;
+    uint64_t rx_bytes;
+    uint64_t rx_dropped;
+
+    uint32_t tx_interrupts;
+    uint32_t rx_interrupts;
+};
 
 #ifdef __V3VEE__
 
@@ -40,7 +56,7 @@ extern int vnet_debug;
 
 #define V3_Net_Print(level, fmt, args...)                                      \
     do {                                                               \
-       if(level <= vnet_debug) {   \
+       if(level <= net_debug) {   \
            extern struct v3_os_hooks * os_hooks;                       \
            if ((os_hooks) && (os_hooks)->print) {                      \
                (os_hooks)->print((fmt), ##args);                       \
@@ -48,19 +64,7 @@ extern int vnet_debug;
        }                                                       \
     } while (0)        
 
-struct nic_statistics {
-    uint64_t tx_pkts;
-    uint64_t tx_bytes;
-    uint64_t tx_dropped;
-       
-    uint64_t rx_pkts;
-    uint64_t rx_bytes;
-    uint64_t rx_dropped;
 
-    uint32_t tx_interrupts;
-    uint32_t rx_interrupts;
-};
-    
 static inline int is_multicast_ethaddr(const uint8_t * addr)
 {
     V3_ASSERT(ETH_ALEN == 6);
index 85babbe..949f0b2 100644 (file)
@@ -101,7 +101,12 @@ int v3_vnet_add_bridge(struct v3_vm_info * vm,
                       struct v3_vnet_bridge_ops * ops,
                       uint8_t type,
                       void * priv_data);
+
+void v3_vnet_del_bridge(uint8_t type);
+
 int v3_vnet_add_route(struct v3_vnet_route route);
+void v3_vnet_del_route(uint32_t route_idx);
+
 int v3_vnet_send_pkt(struct v3_vnet_pkt * pkt, void * private_data, int synchronize);
 int v3_vnet_find_dev(uint8_t  * mac);
 int v3_vnet_stat(struct vnet_stat * stats);
index 631d240..5fe3cff 100644 (file)
@@ -212,8 +212,8 @@ static inline void vnet_reset_timer(struct vnet_timer * timer,
 
 #define Vnet_Print(level, fmt, args...)                                        \
     do {                                                               \
-       extern int vnet_debug;                                          \
-       if(level <= vnet_debug) {                                       \
+       extern int net_debug;                                           \
+       if(level <= net_debug) {                                        \
            extern struct vnet_host_hooks * host_hooks;                 \
            if ((host_hooks) && (host_hooks)->print) {                  \
                (host_hooks)->print((fmt), ##args);                     \
@@ -265,6 +265,7 @@ static inline void vnet_unlock_irqrestore(vnet_lock_t lock, addr_t irq_state) {
 
 
 void init_vnet(struct vnet_host_hooks * hooks);
+void deinit_vnet(void);
 
 
 #endif
index 642b259..3c519aa 100644 (file)
 #define PrintDebug(fmt, args...)
 #endif
 
+#ifndef V3_CONFIG_VNET
+static int net_debug = 0;
+#endif
+
 #define TX_QUEUE_SIZE 4096
 #define RX_QUEUE_SIZE 4096
 #define CTRL_QUEUE_SIZE 64
@@ -199,7 +203,7 @@ static int tx_one_pkt(struct guest_info * core,
     }
 
     V3_Net_Print(2, "Virtio-NIC: virtio_tx: size: %d\n", len);
-    if(vnet_debug >= 4){
+    if(net_debug >= 4){
        v3_hexdump(buf, len, NULL, 0);
     }
 
@@ -248,11 +252,15 @@ static inline int get_desc_count(struct virtio_queue * q, int index) {
 }
 
 static inline void enable_cb(struct virtio_queue *queue){
-    queue->used->flags &= ~ VRING_NO_NOTIFY_FLAG;
+    if(queue->used){
+       queue->used->flags &= ~ VRING_NO_NOTIFY_FLAG;
+    }
 }
 
 static inline void disable_cb(struct virtio_queue *queue) {
-    queue->used->flags |= VRING_NO_NOTIFY_FLAG;
+    if(queue->used){
+       queue->used->flags |= VRING_NO_NOTIFY_FLAG;
+    }
 }
 
 static int handle_pkt_tx(struct guest_info * core, 
@@ -561,7 +569,7 @@ static int virtio_rx(uint8_t * buf, uint32_t size, void * private_data) {
     unsigned long flags;
 
     V3_Net_Print(2, "Virtio-NIC: virtio_rx: size: %d\n", size);
-    if(vnet_debug >= 4){
+    if(net_debug >= 4){
        v3_hexdump(buf, size, NULL, 0);
     }
 
@@ -804,6 +812,7 @@ static int register_dev(struct virtio_dev_state * virtio,
     return 0;
 }
 
+
 #define RATE_UPPER_THRESHOLD 10  /* 10000 pkts per second, around 100Mbits */
 #define RATE_LOWER_THRESHOLD 1
 #define PROFILE_PERIOD 10000 /*us*/
@@ -815,6 +824,10 @@ static void virtio_nic_timer(struct guest_info * core,
     uint64_t period_us;
     static int profile_ms = 0;
 
+    if(!net_state->status){ /* VNIC is not in working status */
+       return;
+    }
+
     period_us = (1000*cpu_cycles)/cpu_freq;
     net_state->past_us += period_us;
 
@@ -890,12 +903,16 @@ static int connect_fn(struct v3_vm_info * info,
        
     net_state->timer = v3_add_timer(&(info->cores[0]),&timer_ops,net_state);
 
+    PrintError("net_state 0x%p\n", (void *)net_state);
+
     ops->recv = virtio_rx;
     ops->frontend_data = net_state;
     memcpy(ops->fnt_mac, virtio->mac, ETH_ALEN);
 
     net_state->poll_thread = vnet_start_thread(virtio_tx_flush, (void *)net_state, "Virtio_Poll");
 
+    net_state->status = 1;
+
     return 0;
 }
 
index 66761d9..ac484a0 100644 (file)
@@ -54,7 +54,7 @@ static int vnet_nic_send(uint8_t * buf, uint32_t len,
 
     V3_Net_Print(2, "VNET-NIC: send pkt (size: %d, src_id: %d, src_type: %d)\n", 
                   pkt.size, pkt.src_id, pkt.src_type);
-    if(vnet_debug >= 4){
+    if(net_debug >= 4){
        v3_hexdump(buf, len, NULL, 0);
     }
 
index 42c9d3b..8cf2364 100644 (file)
@@ -29,7 +29,7 @@
 #define Vnet_Debug(fmt, args...)
 #endif
 
-int vnet_debug = 0;
+int net_debug = 0;
 
 struct eth_hdr {
     uint8_t dst_mac[ETH_ALEN];
@@ -66,6 +66,8 @@ struct vnet_route_info {
     struct vnet_dev * dst_dev;
     struct vnet_dev * src_dev;
 
+    uint32_t idx;
+
     struct list_head node;
     struct list_head match_node; // used for route matching
 };
@@ -98,8 +100,10 @@ static struct {
     struct list_head routes;
     struct list_head devs;
     
-    int num_routes;
-    int num_devs;
+    uint32_t num_routes;
+    uint32_t route_idx;
+    uint32_t num_devs;
+    uint32_t dev_idx;
 
     struct vnet_brg_dev * bridge;
 
@@ -115,7 +119,7 @@ static struct {
        
 
 #ifdef V3_CONFIG_DEBUG_VNET
-static inline void mac_to_string(uint8_t * mac, char * buf) {
+static inline void mac2str(uint8_t * mac, char * buf) {
     snprintf(buf, 100, "%2x:%2x:%2x:%2x:%2x:%2x", 
             mac[0], mac[1], mac[2],
             mac[3], mac[4], mac[5]);
@@ -124,10 +128,10 @@ static inline void mac_to_string(uint8_t * mac, char * buf) {
 static void print_route(struct v3_vnet_route * route){
     char str[50];
 
-    mac_to_string(route->src_mac, str);
+    mac2str(route->src_mac, str);
     Vnet_Debug("Src Mac (%s),  src_qual (%d)\n", 
               str, route->src_mac_qual);
-    mac_to_string(route->dst_mac, str);
+    mac2str(route->dst_mac, str);
     Vnet_Debug("Dst Mac (%s),  dst_qual (%d)\n", 
               str, route->dst_mac_qual);
     Vnet_Debug("Src dev id (%d), src type (%d)", 
@@ -274,16 +278,36 @@ int v3_vnet_add_route(struct v3_vnet_route route) {
     flags = vnet_lock_irqsave(vnet_state.lock);
 
     list_add(&(new_route->node), &(vnet_state.routes));
-    clear_hash_cache();
-
+    new_route->idx = ++ vnet_state.route_idx;
+    vnet_state.num_routes ++;
+       
     vnet_unlock_irqrestore(vnet_state.lock, flags);
-   
+
+    clear_hash_cache();
 
 #ifdef V3_CONFIG_DEBUG_VNET
     dump_routes();
 #endif
 
-    return 0;
+    return new_route->idx;
+}
+
+
+void v3_vnet_del_route(uint32_t route_idx){
+    struct vnet_route_info * route = NULL;
+    unsigned long flags; 
+
+    flags = vnet_lock_irqsave(vnet_state.lock);
+
+    list_for_each_entry(route, &(vnet_state.routes), node) {
+       if(route->idx == route_idx){
+           list_del(&(route->node));
+           list_del(&(route->match_node));
+           Vnet_Free(route);    
+       }
+    }
+
+    vnet_unlock_irqrestore(vnet_state.lock, flags);
 }
 
 
@@ -319,7 +343,7 @@ static struct route_list * match_route(const struct v3_vnet_pkt * pkt) {
     int max_rank = 0;
     struct list_head match_list;
     struct eth_hdr * hdr = (struct eth_hdr *)(pkt->data);
-    //    uint8_t src_type = pkt->src_type;
+    //  uint8_t src_type = pkt->src_type;
     //  uint32_t src_link = pkt->src_id;
 
 #ifdef V3_CONFIG_DEBUG_VNET
@@ -327,8 +351,8 @@ static struct route_list * match_route(const struct v3_vnet_pkt * pkt) {
        char dst_str[100];
        char src_str[100];
 
-       mac_to_string(hdr->src_mac, src_str);  
-       mac_to_string(hdr->dst_mac, dst_str);
+       mac2str(hdr->src_mac, src_str);  
+       mac2str(hdr->dst_mac, dst_str);
        Vnet_Debug("VNET/P Core: match_route. pkt: SRC(%s), DEST(%s)\n", src_str, dst_str);
     }
 #endif
@@ -447,7 +471,7 @@ int vnet_tx_one_pkt(struct v3_vnet_pkt * pkt, void * private_data) {
     Vnet_Print(2, "VNET/P Core: cpu %d: pkt (size %d, src_id:%d, src_type: %d, dst_id: %d, dst_type: %d)\n",
                  cpu, pkt->size, pkt->src_id, 
                  pkt->src_type, pkt->dst_id, pkt->dst_type);
-    if(vnet_debug >= 4){
+    if(net_debug >= 4){
            v3_hexdump(pkt->data, pkt->size, NULL, 0);
     }
 
@@ -596,7 +620,8 @@ int v3_vnet_add_dev(struct v3_vm_info * vm, uint8_t * mac,
 
     if (dev_by_mac(mac) == NULL) {
        list_add(&(new_dev->node), &(vnet_state.devs));
-       new_dev->dev_id = ++vnet_state.num_devs;
+       new_dev->dev_id = ++ vnet_state.dev_idx;
+       vnet_state.num_devs ++;
     }
 
     vnet_unlock_irqrestore(vnet_state.lock, flags);
@@ -622,7 +647,8 @@ int v3_vnet_del_dev(int dev_id){
     dev = dev_by_id(dev_id);
     if (dev != NULL){
        list_del(&(dev->node));
-       del_routes_by_dev(dev_id);
+       //del_routes_by_dev(dev_id);
+       vnet_state.num_devs --;
     }
        
     vnet_unlock_irqrestore(vnet_state.lock, flags);
@@ -636,7 +662,6 @@ int v3_vnet_del_dev(int dev_id){
 
 
 int v3_vnet_stat(struct vnet_stat * stats){
-       
     stats->rx_bytes = vnet_state.stats.rx_bytes;
     stats->rx_pkts = vnet_state.stats.rx_pkts;
     stats->tx_bytes = vnet_state.stats.tx_bytes;
@@ -645,7 +670,7 @@ int v3_vnet_stat(struct vnet_stat * stats){
     return 0;
 }
 
-static void free_devices(){
+static void deinit_devices_list(){
     struct vnet_dev * dev = NULL; 
 
     list_for_each_entry(dev, &(vnet_state.devs), node) {
@@ -654,7 +679,7 @@ static void free_devices(){
     }
 }
 
-static void free_routes(){
+static void deinit_routes_list(){
     struct vnet_route_info * route = NULL; 
 
     list_for_each_entry(route, &(vnet_state.routes), node) {
@@ -706,6 +731,26 @@ int v3_vnet_add_bridge(struct v3_vm_info * vm,
     return 0;
 }
 
+
+void v3_vnet_del_bridge(uint8_t type) {
+    unsigned long flags;
+    struct vnet_brg_dev * tmp_bridge = NULL;    
+    
+    flags = vnet_lock_irqsave(vnet_state.lock);
+       
+    if (vnet_state.bridge != NULL && vnet_state.bridge->type == type) {
+       tmp_bridge = vnet_state.bridge;
+       vnet_state.bridge = NULL;
+    }
+       
+    vnet_unlock_irqrestore(vnet_state.lock, flags);
+
+    if (tmp_bridge) {
+       Vnet_Free(tmp_bridge);
+    }
+}
+
+
 static int vnet_tx_flush(void *args){
     unsigned long flags;
     struct queue_entry * entry;
@@ -774,8 +819,8 @@ void v3_deinit_vnet(){
 
     vnet_lock_deinit(&(vnet_state.lock));
 
-    free_devices();
-    free_routes();
+    deinit_devices_list();
+    deinit_routes_list();
 
     vnet_free_htable(vnet_state.route_cache, 1, 1);
     Vnet_Free(vnet_state.bridge);
index 9d3bb31..c5d366a 100644 (file)
 
 struct vnet_host_hooks * host_hooks;
 
-
 int vnet_lock_init(vnet_lock_t * lock) {
-    *lock = (addr_t)(host_hooks->mutex_alloc());
-
-    if (!(*lock)) {
-       return -1;
+    if((host_hooks) && host_hooks->mutex_alloc){
+       *lock = (addr_t)(host_hooks->mutex_alloc());
+       
+       if (*lock) {
+           return 0;
+       }
     }
 
-    return 0;
+    return -1;
 }
 
 
 struct vnet_thread * vnet_start_thread(int (*func)(void *), void *arg, char * name){
-    struct vnet_thread * thread;
-
-    thread = Vnet_Malloc(sizeof(struct vnet_thread));
-       
-    thread->host_thread = host_hooks->thread_start(func, arg, name);
+    if((host_hooks) && host_hooks->thread_start){
+       struct vnet_thread * thread = Vnet_Malloc(sizeof(struct vnet_thread));
+       thread->host_thread = host_hooks->thread_start(func, arg, name);
 
-    if(thread->host_thread == NULL){
+       if(thread->host_thread){
+           return thread;
+       }
        Vnet_Free(thread);
-       return NULL;
     }
 
-    return thread;
+    return NULL;
 }
 
 
@@ -54,15 +54,13 @@ struct vnet_thread * vnet_start_thread(int (*func)(void *), void *arg, char * na
 struct vnet_timer * vnet_create_timer(unsigned long interval, 
                                      void (* timer_fun)(void * priv_data), 
                                      void * priv_data){
-    struct vnet_timer * timer = NULL; 
-
     if((host_hooks) && host_hooks->timer_create){
-       timer = Vnet_Malloc(sizeof(struct vnet_timer));
-
+       struct vnet_timer * timer = Vnet_Malloc(sizeof(struct vnet_timer));
        timer->host_timer = host_hooks->timer_create(interval, timer_fun, priv_data);
+       return timer;
     }
 
-    return timer;
+    return NULL;
  }
 
 
@@ -72,3 +70,8 @@ void init_vnet(struct vnet_host_hooks * hooks){
 }
 
 
+void deinit_vnet(){
+    host_hooks = NULL;
+    v3_deinit_vnet();
+}
+