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.


Resoved conflict on merge of 8254.c
Patrick Bridges [Tue, 24 May 2011 17:03:35 +0000 (11:03 -0600)]
31 files changed:
linux_module/Makefile
linux_module/palacios-dev.c
linux_module/palacios-graphics-console.c
linux_module/palacios-host-dev-user.h
linux_module/palacios-host-dev.c
linux_module/palacios-packet.h
linux_module/palacios-socket.c
linux_module/palacios-socket.h
linux_module/palacios-vm.c
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
linux_module/palacios.h
linux_usr/Makefile
linux_usr/v3_os_debug.c [new file with mode: 0644]
linux_usr/v3_user_host_dev.c
palacios/include/palacios/vmm_ethernet.h
palacios/include/vnet/vnet.h
palacios/include/vnet/vnet_host.h
palacios/src/devices/8254.c
palacios/src/devices/Kconfig
palacios/src/devices/apic.c
palacios/src/devices/lnx_virtio_nic.c
palacios/src/devices/vnet_nic.c
palacios/src/interfaces/Makefile
palacios/src/interfaces/null.c [new file with mode: 0644]
palacios/src/palacios/svm_handler.c
palacios/src/palacios/vmm_queue.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 be62f33..cf8e0fe 100644 (file)
@@ -61,7 +61,7 @@ static int register_vm( void ) {
     for (i = 0; i < sizeof(v3_minor_map); i++) {
        if (v3_minor_map[i] != 0xff) {
            for (j = 0; j < 8; j++) {
-               if (!v3_minor_map[i] & (0x1 << j)) {
+               if (!(v3_minor_map[i] & (0x1 << j))) {
                    avail = 1;
                    v3_minor_map[i] |= (0x1 << j);
                    break;
@@ -121,7 +121,7 @@ static long v3_dev_ioctl(struct file * filp,
            guest->img_size = user_image.size;
 
            printk("Allocating kernel memory for guest image (%llu bytes)\n", user_image.size);
-           guest->img = kmalloc(guest->img_size, GFP_KERNEL);
+           guest->img = vmalloc(guest->img_size);
 
            if (IS_ERR(guest->img)) {
                printk("Error: Could not allocate space for guest image\n");
@@ -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 54b2e17..4f1334f 100644 (file)
@@ -7,32 +7,32 @@
  */
 
 
-#define V3_VM_HOST_DEV_CONNECT 512+1
+#define V3_VM_HOST_DEV_CONNECT (10244+1)
 
 /* to detemine whether a host request is available, poll the fd for read */
 
 /* make a request for reading/writing guest or injecting irq */
 /* the arguemnt is a pointer to a palacios_host_dev_user_op struct */
 /* return is negative on error, positive to indicate bytes read/written or irq injected*/
-#define V3_HOST_DEV_USER_REQUEST_PUSH_IOCTL  1
+#define V3_HOST_DEV_USER_REQUEST_PUSH_IOCTL  (10244+2)
 
 /* find out the size of the current host request, if one is pending */
 /* you find out if one is pending by read poll/select on the fd */
 /* the argument is a pointer to a uint64_t that will give the total size */
 /* ioctl returns 1 if a request is ready, 0 if there is no request */
 /* -EFAULT if there is a an error */
-#define V3_HOST_DEV_HOST_REQUEST_SIZE_IOCTL  2
+#define V3_HOST_DEV_HOST_REQUEST_SIZE_IOCTL  (10244+3)
 
 /* get the current host request, if one is available */
 /* the argument is a pointer to a palacios_host_dev_host_request_response */
 /* of the needed size */
 /* ioctl returns 1 if a request is ready+copied, 0 if there is no request */
 /* -EFAULT if there is a an error */
-#define V3_HOST_DEV_HOST_REQUEST_PULL_IOCTL  3
+#define V3_HOST_DEV_HOST_REQUEST_PULL_IOCTL  (10244+4)
 
 /* write back the response to the previously pulled host request */
 /* the argument is a pointer to a palacios_host_dev_host_request_response */
-#define V3_HOST_DEV_USER_RESPONSE_PUSH_IOCTL 4
+#define V3_HOST_DEV_USER_RESPONSE_PUSH_IOCTL (10244+5)
 
 
 #ifdef __KERNEL__
index 686c962..c20e0fa 100644 (file)
@@ -266,12 +266,14 @@ static int host_dev_release(struct inode * i, struct file * filp)
     return 0;
 }
 
+
 static int host_dev_ioctl(struct inode *ip, struct file *fp, unsigned int val, unsigned long arg)
 {
     void __user *argp = (void __user *)arg;
 
     struct palacios_host_device_user *dev = fp->private_data;
 
+
     if (!dev->connected) { 
        return -EFAULT;
     }
@@ -381,7 +383,7 @@ static int host_dev_ioctl(struct inode *ip, struct file *fp, unsigned int val, u
            }
            
            spin_unlock_irqrestore(&(dev->lock),f);
-           
+
            return 1; // have request for you
            
        }
@@ -462,6 +464,8 @@ static int host_dev_ioctl(struct inode *ip, struct file *fp, unsigned int val, u
 }
 
 
+
+
 static struct file_operations host_dev_fops = {
     .poll     = host_dev_poll,
     .release  = host_dev_release,
@@ -846,7 +850,7 @@ static uint64_t palacios_host_dev_write_io(v3_host_dev_t hostdev,
        spin_unlock_irqrestore(&(dev->lock),f);
        return 0;
     }
-    
+
     // resize request and response in case they will need it
     palacios_resize_reqresp(&(dev->req),len,0); // make room for data
 
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
index 6f65df6..dd422c3 100644 (file)
@@ -215,7 +215,7 @@ int start_palacios_vm(void * arg)  {
     printk("palacios: launching vm\n");
 
 
-#if V3_CONFIG_EXT_INSPECTOR
+#ifdef V3_CONFIG_EXT_INSPECTOR
     inspect_vm(guest);
 #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 b161832..9fe9c29 100644 (file)
 #define V3_VM_STREAM_CONNECT 21
 #define V3_VM_STOP 22
 
-#define V3_VM_FB_INPUT 256+1
-#define V3_VM_FB_QUERY 256+2
+#define V3_VM_FB_INPUT (256+1)
+#define V3_VM_FB_QUERY (256+2)
 
-#define V3_VM_HOST_DEV_CONNECT 512+1
+#define V3_VM_HOST_DEV_CONNECT (10244+1)
 
 
 struct v3_guest_img {
@@ -72,7 +72,7 @@ struct v3_guest {
     struct palacios_console console;
 #endif
 
-#ifdef V3_CONFIG_CONSOLE
+#ifdef V3_CONFIG_GRAPHICS_CONSOLE
     struct palacios_graphics_console graphics_console;
 #endif
 
index c2a23aa..439494c 100644 (file)
@@ -1,4 +1,4 @@
-all: v3_ctrl v3_stop v3_cons v3_mem v3_monitor v3_serial v3_net v3_user_host_dev_example
+all: v3_ctrl v3_stop v3_cons v3_mem v3_monitor v3_serial v3_net v3_user_host_dev_example v3_os_debug
 
 
 
@@ -27,5 +27,9 @@ v3_net : v3_net.c v3_ctrl.h
 v3_user_host_dev_example: v3_user_host_dev_example.c v3_user_host_dev.h v3_user_host_dev.c
        gcc -static -I../linux_module v3_user_host_dev_example.c v3_user_host_dev.c -o v3_user_host_dev_example
 
+v3_os_debug: v3_os_debug.c v3_user_host_dev.h v3_user_host_dev.c
+       gcc -static -I../linux_module v3_os_debug.c v3_user_host_dev.c -o v3_os_debug
+
+
 clean:
-       rm -f v3_ctrl v3_cons v3_mem v3_monitor v3_serial v3_net
+       rm -f v3_ctrl v3_cons v3_mem v3_monitor v3_serial v3_net v3_user_host_dev_example v3_os_debug
diff --git a/linux_usr/v3_os_debug.c b/linux_usr/v3_os_debug.c
new file mode 100644 (file)
index 0000000..c530964
--- /dev/null
@@ -0,0 +1,128 @@
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <sys/select.h>
+#include <malloc.h>
+
+#include "v3_user_host_dev.h"
+
+void usage()
+{
+    fprintf(stderr,"v3_user_host_dev_example /dev/v3-vm0 user:mydev busywait|select\n");
+}
+
+
+int do_work(struct palacios_host_dev_host_request_response *req, 
+           struct palacios_host_dev_host_request_response **resp)
+{
+    uint64_t datasize;
+
+    switch (req->type) {
+    case PALACIOS_HOST_DEV_HOST_REQUEST_WRITE_IO: {
+      if (req->port==0xc0c0) {
+       uint64_t i;
+       uint64_t numchars;
+       numchars = req->data_len - sizeof(struct palacios_host_dev_host_request_response);
+       for (i=0;i<numchars;i++) { 
+         putchar(req->data[i]);
+       }
+       *resp = malloc(sizeof(struct palacios_host_dev_host_request_response));
+       **resp=*req;
+       (*resp)->len = (*resp)->data_len = sizeof(struct palacios_host_dev_host_request_response);
+       (*resp)->op_len = numchars;
+      } else {
+       printf("Huh?  Unknown port %d\n",req->port);
+      }
+    }
+      break;
+
+      default:
+       printf("Huh?  Unknown request %d\n", req->type);
+    }
+    
+    
+    return 0;
+}
+
+int main(int argc, char *argv[])
+{
+    int devfd;
+    int mode=0;
+    char *vm, *url;
+
+    if (argc!=4) { 
+       usage();
+       exit(-1);
+    }
+    
+    vm=argv[1];
+    url=argv[2];
+    mode = argv[3][0]=='s';
+
+    fprintf(stderr,"Attempting to rendezvous with host device %s on vm %s\n", url, vm);
+    
+    if ((devfd = v3_user_host_dev_rendezvous(vm,url))<0) { 
+       perror("failed to rendezvous");
+       exit(-1);
+    }
+    
+    fprintf(stderr,"Rendezvous succeeded, I will now operate in %s mode\n", mode==0 ? "busywait" : "select");
+    
+    if (mode==0) { 
+       //busywait
+
+       struct palacios_host_dev_host_request_response *req;
+       struct palacios_host_dev_host_request_response *resp;
+       uint64_t datasize;
+
+       while (1) { 
+           while (!(v3_user_host_dev_have_request(devfd))) { 
+           }
+           v3_user_host_dev_pull_request(devfd, &req);
+
+           do_work(req, &resp);
+           
+           v3_user_host_dev_push_response(devfd, resp);
+
+           free(resp);
+           free(req);
+       }
+    } else {
+
+       struct palacios_host_dev_host_request_response *req;
+       struct palacios_host_dev_host_request_response *resp;
+       uint64_t datasize;
+       fd_set   readset;
+       int rc;
+
+       // select-based operation so that you can wait for multiple things
+       
+       while (1) { 
+           FD_ZERO(&readset);
+           FD_SET(devfd,&readset);
+
+           rc = select(devfd+1, &readset, 0, 0, 0);  // pick whatever you want to select on, just include devfd
+
+           if (rc>0) { 
+               if (FD_ISSET(devfd,&readset)) { 
+                   // a request is read for us!
+                   v3_user_host_dev_pull_request(devfd, &req);
+
+                   do_work(req, &resp);
+                   
+                   v3_user_host_dev_push_response(devfd, resp);
+                   
+                   free(resp);
+                   free(req);
+               }
+           }
+       }
+    }
+
+    v3_user_host_dev_depart(devfd);
+
+    return 0;
+                   
+}
index 8fe121a..709db76 100644 (file)
@@ -2,6 +2,8 @@
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <malloc.h>
+#include <string.h>
+#include <stdio.h>
 
 #include "v3_user_host_dev.h"
 
@@ -10,12 +12,17 @@ int v3_user_host_dev_rendezvous(char *vmdev, char *url)
 {
     int vmfd;
     int devfd;
+    char buf[256];
+
+
+    strcpy(buf,url);
+    buf[255]=0;
 
     if ((vmfd=open(vmdev,O_RDWR))<0) { 
        return -1;
     }
 
-    devfd = ioctl(vmfd,V3_VM_HOST_DEV_CONNECT,url);
+    devfd = ioctl(vmfd,V3_VM_HOST_DEV_CONNECT,buf);
     
     close(vmfd);
 
@@ -32,7 +39,9 @@ int v3_user_host_dev_have_request(int devfd)
 {
     uint64_t len;
 
-    return ioctl(devfd,V3_HOST_DEV_HOST_REQUEST_SIZE_IOCTL,&len)==1;
+    int rc=ioctl(devfd,V3_HOST_DEV_HOST_REQUEST_SIZE_IOCTL,&len);
+
+    return rc==1;
 }
 
 int v3_user_host_dev_pull_request(int devfd, struct palacios_host_dev_host_request_response **req)
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 fee0e1a..fcde0a1 100644 (file)
@@ -54,8 +54,8 @@
  */
 typedef enum {NOT_RUNNING, PENDING, RUNNING} channel_run_state_t;
 typedef enum {NOT_WAITING, WAITING_LOBYTE, WAITING_HIBYTE} channel_access_state_t;
-typedef enum {LATCH_COUNT, LOBYTE_ONLY, HIBYTE_ONLY, LOBYTE_HIBYTE} channel_access_mode_t;
-typedef enum {IRQ_ON_TERM_CNT, ONE_SHOT, RATE_GEN, SQR_WAVE, SW_STROBE, HW_STROBE} channel_op_mode_t;
+typedef enum {LATCH_COUNT = 0, LOBYTE_ONLY = 1, HIBYTE_ONLY = 2, LOBYTE_HIBYTE = 3} channel_access_mode_t;
+typedef enum {IRQ_ON_TERM_CNT = 0, ONE_SHOT = 1, RATE_GEN = 2, SQR_WAVE = 3, SW_STROBE = 4, HW_STROBE = 5} channel_op_mode_t;
 
 
 struct channel {
@@ -165,7 +165,7 @@ static int handle_crystal_tics(struct pit * pit, struct channel * ch, uint_t osc
     } else {
        ushort_t reload_val = ch->reload_value; 
 
-       if (ch->op_mode == SW_STROBE) {
+       if ((ch->op_mode == SW_STROBE) || (ch->op_mode == IRQ_ON_TERM_CNT)) {
            reload_val = 0xffff;
        }
 
index 15be9a4..3610f2f 100644 (file)
@@ -454,6 +454,7 @@ config SERIAL_UART
 
 config CHAR_STREAM
        bool "Stream based character frontend"
+       depends on STREAM
        default n
        help
          Include Stream based character device frontend
index 5a2856a..9bf7438 100644 (file)
@@ -36,7 +36,7 @@
  * 1. Queue locks. Actual irq insertions are done via queueing irq ops at the dest apic. 
  *    The destination apic's core is responsible for draining the queue, and actually 
  *    setting the vector table. 
- * 2. State locks. This is a standard lock taken when internal apic state is read/written. 
+ * 2. State lock. This is a standard lock taken when internal apic state is read/written. 
  *    When an irq's destination is determined this lock is taken to examine the apic's 
  *    addressability. 
  * 3. VM barrier lock. This is taken when actual VM core state is changed (via SIPI). 
@@ -179,6 +179,7 @@ struct apic_msr {
 
 
 
+
 typedef enum {INIT_ST, 
              SIPI, 
              STARTED} ipi_state_t; 
@@ -239,7 +240,7 @@ struct apic_state {
 
     struct v3_timer * timer;
 
-    v3_lock_t state_lock;
+
     struct v3_queue irq_queue;
 
     uint32_t eoi;
@@ -253,6 +254,8 @@ struct apic_state {
 struct apic_dev_state {
     int num_apics;
   
+    v3_lock_t state_lock;
+
     struct apic_state apics[0];
 } __attribute__((packed));
 
@@ -377,6 +380,9 @@ static int write_apic_msr(struct guest_info * core, uint_t msr, v3_msr_t src, vo
 }
 
 
+
+
+
 // irq_num is the bit offset into a 256 bit buffer...
 static int activate_apic_irq(struct apic_state * apic, uint32_t irq_num) {
     int major_offset = (irq_num & ~0x00000007) >> 3;
@@ -386,13 +392,6 @@ static int activate_apic_irq(struct apic_state * apic, uint32_t irq_num) {
     uint8_t flag = 0x1 << minor_offset;
 
 
-    if (irq_num <= 15 || irq_num > 255) {
-       PrintError("apic %u: core %d: Attempting to raise an invalid interrupt: %d\n", 
-                  apic->lapic_id.val, apic->core->vcpu_id, irq_num);
-       return -1;
-    }
-
-
     PrintDebug("apic %u: core %d: Raising APIC IRQ %d\n", apic->lapic_id.val, apic->core->vcpu_id, irq_num);
 
     if (*req_location & flag) {
@@ -412,6 +411,30 @@ static int activate_apic_irq(struct apic_state * apic, uint32_t irq_num) {
 }
 
 
+static int add_apic_irq_entry(struct apic_state * apic, uint8_t irq_num) {
+
+    if (irq_num <= 15) {
+       PrintError("core %d: Attempting to raise an invalid interrupt: %d\n", 
+                   apic->core->vcpu_id, irq_num);
+       return -1;
+    }
+
+    v3_enqueue(&(apic->irq_queue), (addr_t)irq_num);
+
+    return 0;
+}
+
+static void drain_irq_entries(struct apic_state * apic) {
+    uint32_t irq = 0;
+
+    while ((irq = (uint32_t)v3_dequeue(&(apic->irq_queue))) != 0) {
+       activate_apic_irq(apic, irq);
+    }
+
+}
+
+
+
 
 static int get_highest_isr(struct apic_state * apic) {
     int i = 0, j = 0;
@@ -540,7 +563,7 @@ static int activate_internal_irq(struct apic_state * apic, apic_irq_type_t int_t
 
     if (del_mode == APIC_FIXED_DELIVERY) {
        //PrintDebug("Activating internal APIC IRQ %d\n", vec_num);
-       return activate_apic_irq(apic, vec_num);
+       return add_apic_irq_entry(apic, vec_num);
     } else {
        PrintError("apic %u: core ?: Unhandled Delivery Mode\n", apic->lapic_id.val);
        return -1;
@@ -549,77 +572,108 @@ static int activate_internal_irq(struct apic_state * apic, apic_irq_type_t int_t
 
 
 
-static inline int should_deliver_cluster_ipi(struct guest_info * dst_core, 
+static inline int should_deliver_cluster_ipi(struct apic_dev_state * apic_dev,
+                                            struct guest_info * dst_core, 
                                             struct apic_state * dst_apic, uint8_t mda) {
 
+    int ret = 0;
+
+
     if         ( ((mda & 0xf0) == (dst_apic->log_dst.dst_log_id & 0xf0)) &&  /* (I am in the cluster and */
          ((mda & 0x0f) & (dst_apic->log_dst.dst_log_id & 0x0f)) ) {  /*  I am in the set)        */
+       ret = 1;
+    } else {
+       ret = 0;
+    }
+
 
+    if (ret == 1) {
        PrintDebug("apic %u core %u: accepting clustered IRQ (mda 0x%x == log_dst 0x%x)\n",
                   dst_apic->lapic_id.val, dst_core->vcpu_id, mda, 
                   dst_apic->log_dst.dst_log_id);
-       
-       return 1;
     } else {
        PrintDebug("apic %u core %u: rejecting clustered IRQ (mda 0x%x != log_dst 0x%x)\n",
                   dst_apic->lapic_id.val, dst_core->vcpu_id, mda, 
                   dst_apic->log_dst.dst_log_id);
-       return 0;
     }
+
+    return ret;
+
 }
 
-static inline int should_deliver_flat_ipi(struct guest_info * dst_core,
+static inline int should_deliver_flat_ipi(struct apic_dev_state * apic_dev,
+                                         struct guest_info * dst_core,
                                          struct apic_state * dst_apic, uint8_t mda) {
 
-    if (dst_apic->log_dst.dst_log_id & mda) {  // I am in the set 
+    int ret = 0;
 
-       PrintDebug("apic %u core %u: accepting flat IRQ (mda 0x%x == log_dst 0x%x)\n",
-                  dst_apic->lapic_id.val, dst_core->vcpu_id, mda, 
-                  dst_apic->log_dst.dst_log_id);
 
-       return 1;
+    if ((dst_apic->log_dst.dst_log_id & mda) != 0) {  // I am in the set 
+       ret = 1;
+    } else {
+       ret = 0;
+    }
 
-  } else {
 
+    if (ret == 1) {
+       PrintDebug("apic %u core %u: accepting flat IRQ (mda 0x%x == log_dst 0x%x)\n",
+                  dst_apic->lapic_id.val, dst_core->vcpu_id, mda, 
+                  dst_apic->log_dst.dst_log_id);
+    } else {
        PrintDebug("apic %u core %u: rejecting flat IRQ (mda 0x%x != log_dst 0x%x)\n",
                   dst_apic->lapic_id.val, dst_core->vcpu_id, mda, 
                   dst_apic->log_dst.dst_log_id);
-       return 0;
-  }
+    }
+
+
+    return ret;
 }
 
 
 
-static int should_deliver_ipi(struct guest_info * dst_core, 
+static int should_deliver_ipi(struct apic_dev_state * apic_dev, 
+                             struct guest_info * dst_core, 
                              struct apic_state * dst_apic, uint8_t mda) {
+    addr_t flags = 0;
+    int ret = 0;
 
+    flags = v3_lock_irqsave(apic_dev->state_lock);
 
     if (dst_apic->dst_fmt.model == 0xf) {
 
        if (mda == 0xff) {
            /* always deliver broadcast */
-           return 1;
+           ret = 1;
+       } else {
+           ret = should_deliver_flat_ipi(apic_dev, dst_core, dst_apic, mda);
        }
-
-       return should_deliver_flat_ipi(dst_core, dst_apic, mda);
-
     } else if (dst_apic->dst_fmt.model == 0x0) {
 
        if (mda == 0xff) {
            /*  always deliver broadcast */
-           return 1;
+           ret = 1;
+       } else {
+           ret = should_deliver_cluster_ipi(apic_dev, dst_core, dst_apic, mda);
        }
 
-       return should_deliver_cluster_ipi(dst_core, dst_apic, mda);
-
     } else {
+       ret = -1;
+    }
+    
+    v3_unlock_irqrestore(apic_dev->state_lock, flags);
+
+
+    if (ret == -1) {
        PrintError("apic %u core %u: invalid destination format register value 0x%x for logical mode delivery.\n", 
                   dst_apic->lapic_id.val, dst_core->vcpu_id, dst_apic->dst_fmt.model);
-       return -1;
     }
+
+    return ret;
 }
 
 
+
+
 // Only the src_apic pointer is used
 static int deliver_ipi(struct apic_state * src_apic, 
                       struct apic_state * dst_apic, 
@@ -636,21 +690,17 @@ static int deliver_ipi(struct apic_state * src_apic,
            // lowest priority - 
            // caller needs to have decided which apic to deliver to!
 
-           int do_xcall;
-
            PrintDebug("delivering IRQ %d to core %u\n", vector, dst_core->vcpu_id); 
 
-           do_xcall = activate_apic_irq(dst_apic, vector);
+           add_apic_irq_entry(dst_apic, vector);
            
-
-
+#ifdef V3_CONFIG_MULTITHREAD_OS
            if (dst_apic != src_apic) { 
                PrintDebug(" non-local core with new interrupt, forcing it to exit now\n"); 
-
-#ifdef V3_CONFIG_MULTITHREAD_OS
                v3_interrupt_cpu(dst_core->vm_info, dst_core->pcpu_id, 0);
-#endif
            }
+#endif
+
 
            break;
        }
@@ -732,24 +782,29 @@ static int deliver_ipi(struct apic_state * src_apic,
     
 }
 
-static struct apic_state * find_physical_apic(struct apic_dev_state *apic_dev, struct int_cmd_reg *icr)
-{
+static struct apic_state * find_physical_apic(struct apic_dev_state * apic_dev, uint32_t dst_idx) {
+    struct apic_state * dst_apic = NULL;
+    addr_t flags;
     int i;
-    
-    if ( (icr->dst > 0) && (icr->dst < apic_dev->num_apics) ) { 
+
+    flags = v3_lock_irqsave(apic_dev->state_lock);
+
+    if ( (dst_idx > 0) && (dst_idx < apic_dev->num_apics) ) { 
        // see if it simply is the core id
-       if (apic_dev->apics[icr->dst].lapic_id.val == icr->dst) { 
-           return &(apic_dev->apics[icr->dst]);
+       if (apic_dev->apics[dst_idx].lapic_id.val == dst_idx) { 
+            dst_apic = &(apic_dev->apics[dst_idx]);
        }
     }
 
     for (i = 0; i < apic_dev->num_apics; i++) { 
-       if (apic_dev->apics[i].lapic_id.val == icr->dst) { 
-           return &(apic_dev->apics[i]);
+       if (apic_dev->apics[i].lapic_id.val == dst_idx) { 
+           dst_apic =  &(apic_dev->apics[i]);
        }
     }
-    
-    return NULL;
+
+    v3_unlock_irqrestore(apic_dev->state_lock, flags);
+
+    return dst_apic;
 
 }
 
@@ -775,7 +830,7 @@ static int route_ipi(struct apic_dev_state * apic_dev,
        case APIC_SHORTHAND_NONE:  // no shorthand
            if (icr->dst_mode == APIC_DEST_PHYSICAL) { 
 
-               dest_apic = find_physical_apic(apic_dev, icr);
+               dest_apic = find_physical_apic(apic_dev, icr->dst);
                
                if (dest_apic == NULL) { 
                    PrintError("apic: Attempted send to unregistered apic id=%u\n", icr->dst);
@@ -807,7 +862,7 @@ static int route_ipi(struct apic_dev_state * apic_dev,
                        
                        dest_apic = &(apic_dev->apics[i]);
                        
-                       del_flag = should_deliver_ipi(dest_apic->core, dest_apic, mda);
+                       del_flag = should_deliver_ipi(apic_dev, dest_apic->core, dest_apic, mda);
                        
                        if (del_flag == -1) {
 
@@ -822,11 +877,11 @@ static int route_ipi(struct apic_dev_state * apic_dev,
                            }
                        }
                    }
-               } else {  //APIC_LOWEST_DELIVERY
-                   int i;
+               } else {  // APIC_LOWEST_DELIVERY
                    struct apic_state * cur_best_apic = NULL;
                    uint8_t mda = icr->dst;
-                  
+                   int i;
+
                    // logical, lowest priority
 
                    for (i = 0; i < apic_dev->num_apics; i++) { 
@@ -834,7 +889,7 @@ static int route_ipi(struct apic_dev_state * apic_dev,
 
                        dest_apic = &(apic_dev->apics[i]);
                        
-                       del_flag = should_deliver_ipi(dest_apic->core, dest_apic, mda);
+                       del_flag = should_deliver_ipi(apic_dev, dest_apic->core, dest_apic, mda);
                        
                        if (del_flag == -1) {
                            PrintError("apic: Error checking delivery mode\n");
@@ -842,11 +897,18 @@ static int route_ipi(struct apic_dev_state * apic_dev,
                            return -1;
                        } else if (del_flag == 1) {
                            // update priority for lowest priority scan
+                           addr_t flags = 0;
+
+                           flags = v3_lock_irqsave(apic_dev->state_lock);
+
                            if (cur_best_apic == 0) {
                                cur_best_apic = dest_apic;  
                            } else if (dest_apic->task_prio.val < cur_best_apic->task_prio.val) {
                                cur_best_apic = dest_apic;
                            } 
+
+                           v3_unlock_irqrestore(apic_dev->state_lock, flags);
+
                        }                       
                    }
 
@@ -1189,6 +1251,7 @@ static int apic_write(struct guest_info * core, addr_t guest_addr, void * src, u
     addr_t reg_addr  = guest_addr - apic->base_addr;
     struct apic_msr * msr = (struct apic_msr *)&(apic->base_addr_msr.value);
     uint32_t op_val = *(uint32_t *)src;
+    addr_t flags = 0;
 
     PrintDebug("apic %u: core %u: at %p and priv_data is at %p\n",
               apic->lapic_id.val, core->vcpu_id, apic, priv_data);
@@ -1258,10 +1321,14 @@ static int apic_write(struct guest_info * core, addr_t guest_addr, void * src, u
        case LDR_OFFSET:
            PrintDebug("apic %u: core %u: setting log_dst.val to 0x%x\n",
                       apic->lapic_id.val, core->vcpu_id, op_val);
+           flags = v3_lock_irqsave(apic_dev->state_lock);
            apic->log_dst.val = op_val;
+           v3_unlock_irqrestore(apic_dev->state_lock, flags);
            break;
        case DFR_OFFSET:
+           flags = v3_lock_irqsave(apic_dev->state_lock);
            apic->dst_fmt.val = op_val;
+           v3_unlock_irqrestore(apic_dev->state_lock, flags);
            break;
        case SPURIOUS_INT_VEC_OFFSET:
            apic->spurious_int.val = op_val;
@@ -1395,11 +1462,15 @@ static int apic_write(struct guest_info * core, addr_t guest_addr, void * src, u
 static int apic_intr_pending(struct guest_info * core, void * private_data) {
     struct apic_dev_state * apic_dev = (struct apic_dev_state *)(private_data);
     struct apic_state * apic = &(apic_dev->apics[core->vcpu_id]); 
+    int req_irq = 0;    
+    int svc_irq = 0;
 
-    // drain irq QUEUE
+    // Activate all queued IRQ entries
+    drain_irq_entries(apic);
 
-    int req_irq = get_highest_irr(apic);
-    int svc_irq = get_highest_isr(apic);
+    // Check for newly activated entries
+    req_irq = get_highest_irr(apic);
+    svc_irq = get_highest_isr(apic);
 
     //    PrintDebug("apic %u: core %u: req_irq=%d, svc_irq=%d\n",apic->lapic_id.val,info->vcpu_id,req_irq,svc_irq);
 
@@ -1454,25 +1525,16 @@ int v3_apic_raise_intr(struct v3_vm_info * vm, uint32_t irq, uint32_t dst, void
     struct apic_dev_state * apic_dev = (struct apic_dev_state *)
        (((struct vm_device*)dev_data)->private_data);
     struct apic_state * apic = &(apic_dev->apics[dst]); 
-    int do_xcall;
 
     PrintDebug("apic %u core ?: raising interrupt IRQ %u (dst = %u).\n", apic->lapic_id.val, irq, dst); 
 
-    do_xcall = activate_apic_irq(apic, irq);
+    add_apic_irq_entry(apic, irq);
 
-    if (do_xcall < 0) { 
-       PrintError("Failed to activate apic irq\n");
-       return -1;
-    }
-    
-    if (do_xcall > 0 && (V3_Get_CPU() != dst)) {
-#ifdef V3_CONFIG_MULTITHREAD_OS
+#ifdef V3_CONFIG_MULTITHREAD_OS   
+    if ((V3_Get_CPU() != dst)) {
        v3_interrupt_cpu(vm, dst, 0);
-#else
-       V3_ASSERT(0);
-#endif
-
     }
+#endif
 
     return 0;
 }
@@ -1660,6 +1722,7 @@ static int apic_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
                                                  sizeof(struct apic_state) * vm->num_cores);
 
     apic_dev->num_apics = vm->num_cores;
+    v3_lock_init(&(apic_dev->state_lock));
 
     struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, apic_dev);
 
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 15ba807..9d2c6f3 100644 (file)
@@ -7,4 +7,5 @@ obj-$(V3_CONFIG_GRAPHICS_CONSOLE) += vmm_graphics_console.o
 obj-$(V3_CONFIG_KEYED_STREAMS) += vmm_keyed_stream.o
 obj-$(V3_CONFIG_HOST_DEVICE) += vmm_host_dev.o
 
+obj-y += null.o
 
diff --git a/palacios/src/interfaces/null.c b/palacios/src/interfaces/null.c
new file mode 100644 (file)
index 0000000..1828c44
--- /dev/null
@@ -0,0 +1,6 @@
+/** \file
+ * Do nothing module.
+ *
+ * This file only exists to appease the kbuild gods.
+ */
+
index 5749eac..a84d2e1 100644 (file)
@@ -217,7 +217,10 @@ int v3_handle_svm_exit(struct guest_info * info, addr_t exit_code, addr_t exit_i
                return -1;
            }
 
-           break;          
+           break;      
+       case VMEXIT_NMI:
+           // handled by interrupt dispatcher
+           break;
        case VMEXIT_INTR:
            // handled by interrupt dispatch earlier
            break;
index 03cfb6d..20fa255 100644 (file)
@@ -33,19 +33,21 @@ struct v3_queue * v3_create_queue() {
 
 void v3_enqueue(struct v3_queue * queue, addr_t entry) {
     struct v3_queue_entry * q_entry = V3_Malloc(sizeof(struct v3_queue_entry));
+    unsigned int flags = 0;
 
-    v3_lock(queue->lock);
+    flags = v3_lock_irqsave(queue->lock);
     q_entry->entry = entry;
     list_add_tail(&(q_entry->entry_list), &(queue->entries));
     queue->num_entries++;
-    v3_unlock(queue->lock);
+    v3_unlock_irqrestore(queue->lock, flags);
 }
 
 
 addr_t v3_dequeue(struct v3_queue * queue) {
     addr_t entry_val = 0;
+    unsigned int flags = 0;
 
-    v3_lock(queue->lock);
+    flags = v3_lock_irqsave(queue->lock);
     if (!list_empty(&(queue->entries))) {
        struct list_head * q_entry = queue->entries.next;
        struct v3_queue_entry * tmp_entry = list_entry(q_entry, struct v3_queue_entry, entry_list);
@@ -54,7 +56,7 @@ addr_t v3_dequeue(struct v3_queue * queue) {
        list_del(q_entry);
        V3_Free(tmp_entry);
     }
-    v3_unlock(queue->lock);
+    v3_unlock_irqrestore(queue->lock, flags);
 
     return entry_val;
 }
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();
+}
+