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.


Further cleanup of vnet /proc interface
[palacios.git] / linux_module / palacios-vnet-brg.c
index e87d422..efb7d18 100644 (file)
@@ -1,7 +1,8 @@
 /* 
-   Palacios VNET Host Bridge
-   (c) Lei Xia, 2010
- */
+ * Palacios VNET Host Bridge
+ * (c) Lei Xia  2010
+ */ 
+
 #include <linux/spinlock.h>
 #include <linux/seq_file.h>
 #include <linux/proc_fs.h>
 #include <vnet/vnet.h>
 #include <vnet/vnet_hashtable.h>
 #include "palacios-vnet.h"
+#include "palacios.h"
+
 
 #define VNET_SERVER_PORT 9000
 
+#define VNET_YIELD_TIME_USEC 1000
+
 struct vnet_link {
     uint32_t dst_ip;
     uint16_t dst_port;
@@ -99,12 +104,12 @@ static void _delete_link(struct vnet_link * link){
     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", 
+    INFO("VNET Bridge: Link deleted, ip 0x%x, port: %d, idx: %d\n", 
           link->dst_ip, 
           link->dst_port, 
           link->idx);
 
-    kfree(link);
+    palacios_free(link);
     link = NULL;
 }
 
@@ -117,9 +122,9 @@ void vnet_brg_delete_link(uint32_t idx){
 }
 
 static void deinit_links_list(void){
-    struct vnet_link * link;
+    struct vnet_link * link, * tmp_link;
 
-    list_for_each_entry(link, &(vnet_brg_s.link_list), node) {
+    list_for_each_entry_safe(link, tmp_link, &(vnet_brg_s.link_list), node) {
        _delete_link(link);
     }
 }
@@ -138,12 +143,12 @@ static uint32_t _create_link(struct vnet_link * link) {
            break;
 
        default:
-           printk("Unsupported VNET Server Protocol\n");
+           WARNING("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);
+       WARNING("Could not create socket for VNET Link, error %d\n", err);
        return -1;
     }
 
@@ -154,7 +159,7 @@ static uint32_t _create_link(struct vnet_link * link) {
     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);
+       WARNING("Could not connect to remote VNET Server, error %d\n", err);
        return -1;
     }
 
@@ -165,7 +170,7 @@ static uint32_t _create_link(struct vnet_link * link) {
     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", 
+    INFO("VNET Bridge: Link created, ip 0x%x, port: %d, idx: %d, link: %p, protocol: %s\n", 
           link->dst_ip, 
           link->dst_port, 
           link->idx, 
@@ -180,7 +185,7 @@ 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);
+     new_link = palacios_alloc(sizeof(struct vnet_link));
      if (!new_link) {
        return -1;
      }
@@ -192,8 +197,8 @@ uint32_t vnet_brg_add_link(uint32_t ip, uint16_t port, vnet_brg_proto_t proto){
 
      idx = _create_link(new_link);
      if (idx < 0) {
-       printk("Could not create link\n");
-       kfree(new_link);
+       WARNING("Could not create link\n");
+       palacios_free(new_link);
        return -1;
      }
 
@@ -253,8 +258,8 @@ _udp_send(struct socket * sock,
 
 static int 
 _udp_recv(struct socket * sock, 
-        struct sockaddr_in * addr,
-        unsigned char * buf, int len) {
+         struct sockaddr_in * addr,
+         unsigned char * buf, int len, int nonblocking) {
     struct msghdr msg;
     struct iovec iov;
     mm_segment_t oldfs;
@@ -267,7 +272,7 @@ _udp_recv(struct socket * sock,
     iov.iov_base = buf;
     iov.iov_len = len;
     
-    msg.msg_flags = 0;
+    msg.msg_flags = MSG_NOSIGNAL | (nonblocking ? MSG_DONTWAIT : 0);
     msg.msg_name = addr;
     msg.msg_namelen = sizeof(struct sockaddr_in);
     msg.msg_control = NULL;
@@ -298,7 +303,7 @@ send_to_palacios(unsigned char * buf,
     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", 
+       DEBUG("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);
@@ -307,7 +312,7 @@ send_to_palacios(unsigned char * buf,
 
     vnet_brg_s.stats.pkt_to_vmm ++;
 
-    return v3_vnet_send_pkt(&pkt, NULL, 1);
+    return v3_vnet_send_pkt(&pkt, NULL);
 }
 
 
@@ -319,7 +324,7 @@ bridge_send_pkt(struct v3_vm_info * vm,
     struct vnet_link * link;
 
     if(net_debug >= 2){
-       printk("VNET Lnx Host Bridge: packet received from VNET Core ... pkt size: %d, link: %d\n",
+       DEBUG("VNET Lnx Host Bridge: packet received from VNET Core ... pkt size: %d, link: %d\n",
                        pkt->size,
                        pkt->dst_id);
        if(net_debug >= 4){
@@ -341,13 +346,13 @@ bridge_send_pkt(struct v3_vm_info * vm,
                break;  
 
            default:
-               printk("VNET Server: Invalid Link Protocol\n");
+               WARNING("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);
+       INFO("VNET Bridge Linux Host: wrong dst link, idx: %d, discarding the packet\n", pkt->dst_id);
        vnet_brg_s.stats.pkt_drop_vmm ++;
     }
 
@@ -368,12 +373,12 @@ static int init_vnet_serv(void) {
            break;
 
        default:
-           printk("Unsupported VNET Server Protocol\n");
+           WARNING("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);
+       WARNING("Could not create VNET server socket, error: %d\n", err);
        return -1;
     }
 
@@ -384,15 +389,15 @@ static int init_vnet_serv(void) {
     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);
+       WARNING("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);
+    INFO("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);
+           WARNING("VNET Server error listening on port %d, error %d\n", VNET_SERVER_PORT, err);
            return -1;
        }
     }
@@ -406,20 +411,42 @@ static int _udp_server(void * arg) {
     struct vnet_link * link = NULL;
     int len;
 
-    printk("Palacios VNET Bridge: UDP receiving server ..... \n");
+    INFO("Palacios VNET Bridge: UDP receiving server ..... \n");
+
+    pkt = palacios_alloc(MAX_PACKET_LEN);
+
+    if (!pkt) { 
+       ERROR("Unable to allocate packet in VNET UDP Server\n");
+       return -1;
+    }
+
 
-    pkt = kmalloc(MAX_PACKET_LEN, GFP_KERNEL);
     while (!kthread_should_stop()) {
+
+       // This is a NONBLOCKING receive
+       // If we block here, we will never detect that this thread
+       // is being signaled to stop, plus we might go uninterrupted on this core
+       // blocking out access to other threads - leave this NONBLOCKING
+       // unless you know what you are doing
+       len = _udp_recv(vnet_brg_s.serv_sock, &pkt_addr, pkt, MAX_PACKET_LEN, 1); 
+
+
+       // If it would have blocked, we have no packet, and so
+       // we will give other threads on this core a chance
+       if (len==-EAGAIN || len==-EWOULDBLOCK || len==-EINTR) { 
+           palacios_yield_cpu_timed(VNET_YIELD_TIME_USEC);
+           continue;
+       }
        
-       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);
+           WARNING("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");
+           WARNING("VNET Server: No VNET Link matches the src IP\n");
            vnet_brg_s.stats.pkt_drop_phy ++;
            continue;
        }
@@ -431,7 +458,9 @@ static int _udp_server(void * arg) {
        send_to_palacios(pkt, len, link->idx);
     }
 
-    kfree(pkt);
+    INFO("VNET Server: UDP thread exiting\n");
+
+    palacios_free(pkt);
 
     return 0;
 }
@@ -445,8 +474,10 @@ static int _rx_server(void * arg) {
        //accept new connection
        //use select to receive pkt from physical network
        //or create new kthread to handle each connection?
+       WARNING("VNET Server: TCP is not currently supported\n");
+       return -1;
     }else {
-       printk ("VNET Server: Unsupported Protocol\n");
+       WARNING ("VNET Server: Unsupported Protocol\n");
        return -1;
     }
 
@@ -479,25 +510,25 @@ int vnet_bridge_init(void) {
 
     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");
+       WARNING("Failure to initiate VNET link hashtable\n");
        return -1;
     }
        
     if(init_vnet_serv() < 0){
-       printk("Failure to initiate VNET server\n");
+       WARNING("Failure to initiate VNET server\n");
        return -1;
     }
 
-    vnet_brg_s.serv_thread = kthread_run(_rx_server, NULL, "vnet-server");
+    vnet_brg_s.serv_thread = kthread_run(_rx_server, NULL, "vnet_brgd");
 
     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");
+       WARNING("VNET LNX Bridge: Fails to register bridge to VNET core");
     }
 
-    printk("VNET Linux Bridge initiated\n");
+    INFO("VNET Linux Bridge initiated\n");
 
     return 0;
 }
@@ -505,16 +536,29 @@ int vnet_bridge_init(void) {
 
 void vnet_bridge_deinit(void){
 
+    INFO("VNET LNX Bridge Deinit Started\n");
+
     v3_vnet_del_bridge(HOST_LNX_BRIDGE);
 
+    //DEBUG("Stopping bridge service thread\n");
+
     kthread_stop(vnet_brg_s.serv_thread);
+
+    //DEBUG("Releasing bridee service socket\n");
+
     vnet_brg_s.serv_sock->ops->release(vnet_brg_s.serv_sock);
 
+    //DEBUG("Deiniting bridge links\n");
+
     deinit_links_list();
 
+    //DEBUG("Freeing bridge hash tables\n");
+
     vnet_free_htable(vnet_brg_s.ip2link, 0, 0);
 
     vnet_brg_s.status = 0;
+
+    INFO("VNET LNX Bridge Deinit Finished\n");
 }