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.


Linux kernel compatability enhancements (through 3.19)
[palacios.git] / linux_module / palacios-vnet-ctrl.c
index 74e14c4..6dae6bb 100644 (file)
@@ -1,23 +1,8 @@
-/*
- * This file is part of the Palacios Virtual Machine Monitor developed
- * by the V3VEE Project with funding from the United States National
- * Science Foundation and the Department of Energy.
- *
- * The V3VEE Project is a joint project between Northwestern University
- * and the University of New Mexico.  You can find out more at
- * http://www.v3vee.org
- *
- * Copyright (c) 2011, Lei Xia <lxia@northwestern.edu>
- * Copyright (c) 2011, The V3VEE Project <http://www.v3vee.org>
- * All rights reserved.
- *
- * This is free software.  You are permitted to use, redistribute,
- * and modify it under the terms of the GNU General Public License
- * Version 2 (GPLv2).  The accompanying COPYING file contains the
- * full text of the license.
+/* 
+ * Palacios VNET Control Module
+ * (c) Lei Xia  2010
  */
-/* Palacios VNET Control Module */
-
 #include <linux/spinlock.h>
 #include <linux/seq_file.h>
 #include <linux/proc_fs.h>
@@ -37,6 +22,7 @@
 #include <vnet/vnet.h>
 #include <vnet/vnet_hashtable.h>
 #include "palacios-vnet.h"
+#include "palacios.h"
 
 #define VNET_SERVER_PORT 9000
 
@@ -76,10 +62,33 @@ struct vnet_ctrl_state {
 static struct vnet_ctrl_state vnet_ctrl_s;
 
 
+char *skip_blank(char **start)
+{
+    char *cur;
+    
+    do {
+       cur = strsep(start, " \t");
+    } while (cur != NULL && *cur=='\0');
+
+    return cur;
+}
+
+char *skip_lines(char **start)
+{
+    char *cur;
+    
+    do {
+       cur = strsep(start, "\r\n");
+    } while (cur != NULL && *cur=='\0');
+
+    return cur;
+}
+
+
 static int parse_mac_str(char * str, uint8_t * qual, uint8_t * mac) {
     char * token;
 
-    printk("Parsing MAC (%s)\n", str);
+    INFO("Parsing MAC (%s)\n", str);
        
     *qual = MAC_NOSET;
     if(strnicmp("any", str, strlen(str)) == 0){
@@ -95,7 +104,7 @@ static int parse_mac_str(char * str, uint8_t * qual, uint8_t * mac) {
            if (strnicmp("not", token, strlen("not")) == 0) {
                *qual = MAC_NOT;
            } else {
-               printk("Invalid MAC String token (%s)\n", token);
+               WARNING("Invalid MAC String token (%s)\n", token);
                return -1;
            }
        }
@@ -110,15 +119,15 @@ static int parse_mac_str(char * str, uint8_t * qual, uint8_t * mac) {
            for (i = 0; i < 6; i++) {
                token = strsep(&str, ":");
                if (!token) {
-                   printk("Invalid MAC String token (%s)\n", token);
+                   WARNING("Invalid MAC String token (%s)\n", token);
                    return -1;
                }
                mac[i] = simple_strtol(token, &token, 16);
            }
-           printk("MAC: %2x:%2x:%2x:%2x:%2x:%2x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+           DEBUG("MAC: %2x:%2x:%2x:%2x:%2x:%2x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
                
        }else {
-           printk("Invalid MAC String token (%s)\n", token);
+           WARNING("Invalid MAC String token (%s)\n", token);
            return -1;
        }
                
@@ -135,7 +144,7 @@ static int str2mac(char * str, uint8_t * mac){
     for (i = 0; i < ETH_ALEN; i++) {           
        hex = strsep(&str, ":");
        if (!hex) {
-           printk("Invalid MAC String token (%s)\n", str);
+           WARNING("Invalid MAC String token (%s)\n", str);
            return -1;
        }
        mac[i] = simple_strtol(hex, &hex, 16);
@@ -176,41 +185,41 @@ static int parse_route_str(char * str, struct v3_vnet_route * route) {
     struct vnet_link_iter * link = NULL;
 
     // src MAC
-    token = strsep(&str, " ");
+    token = skip_blank(&str);
     if (!token) {
        return -1;
     }
     parse_mac_str(token, &(route->src_mac_qual), route->src_mac);
 
-    // dst MAC
-    token = strsep(&str, " ");
+    // Dst MAC
+    token = skip_blank(&str);
     if (!token) {
        return -1;
     }
     parse_mac_str(token, &(route->dst_mac_qual), route->dst_mac);
 
     // dst LINK type
-    token = strsep(&str, " ");
+    token = skip_blank(&str);
     if (!token) {
        return -1;
     }
-    printk("dst type =(%s)\n", token);
+    INFO("dst type =(%s)\n", token);
     
     if (strnicmp("interface", token, strlen("interface")) == 0) {
        route->dst_type = LINK_INTERFACE;
     } else if (strnicmp("edge", token, strlen("edge")) == 0) {
        route->dst_type = LINK_EDGE;
     } else {
-       printk("Invalid Destination Link Type (%s)\n", token);
+       WARNING("Invalid Destination Link Type (%s)\n", token);
        return -1;
     }
 
     // dst link
-    token = strsep(&str, " ");
+    token = skip_blank(&str);
     if (!token) {
        return -1;
     }
-    printk("dst ID=(%s)\n", token);
+    DEBUG("dst ID=(%s)\n", token);
 
     // Figure out link here
     if (route->dst_type == LINK_EDGE) {
@@ -218,7 +227,7 @@ static int parse_route_str(char * str, struct v3_vnet_route * route) {
 
        // Figure out Link Here
        if (in4_pton(token, strlen(token), (uint8_t *)&(link_ip), '\0', NULL) != 1) {
-           printk("Invalid Dst IP address (%s)\n", token);
+           WARNING("Invalid Dst IP address (%s)\n", token);
            return -EFAULT;
        }
 
@@ -226,26 +235,26 @@ static int parse_route_str(char * str, struct v3_vnet_route * route) {
        if (link != NULL){
            route->dst_id = link->idx;
        }else{
-           printk("can not find dst link %s\n", token);
+           WARNING("can not find dst link %s\n", token);
            return -1;
        }
 
-       printk("link_ip = %d, link_id = %d\n", link_ip, link->idx);     
+       INFO("link_ip = %d, link_id = %d\n", link_ip, link->idx);       
     } else if (route->dst_type == LINK_INTERFACE) {
        uint8_t mac[ETH_ALEN];
        
        if(str2mac(token, mac) == -1){
-          printk("wrong MAC format (%s)\n", token);
+          WARNING("wrong MAC format (%s)\n", token);
           return -1;
        }
           
        route->dst_id = v3_vnet_find_dev(mac);
        if (route->dst_id == -1){
-           printk("can not find dst device %s\n", token);
+           WARNING("can not find dst device %s\n", token);
            return -1;
        }               
     } else {
-       printk("Unsupported dst link type\n");
+       WARNING("Unsupported dst link type\n");
        return -1;
     }
 
@@ -253,9 +262,9 @@ static int parse_route_str(char * str, struct v3_vnet_route * route) {
     route->src_type = -1;
 
     // src LINK
-    token = strsep(&str, " ");
+    token = skip_blank(&str);
 
-    printk("SRC type = %s\n", token);
+    INFO("SRC type = %s\n", token);
 
     if (!token) {
        return -1;
@@ -268,7 +277,7 @@ static int parse_route_str(char * str, struct v3_vnet_route * route) {
     } else if (strnicmp("any", token, strlen("any")) == 0) {
        route->src_type = LINK_ANY;
     } else {
-       printk("Invalid Src link type (%s)\n", token);
+       WARNING("Invalid Src link type (%s)\n", token);
        return -1;
     }
 
@@ -277,7 +286,7 @@ static int parse_route_str(char * str, struct v3_vnet_route * route) {
        route->src_id = -1;
     } else if (route->src_type == LINK_EDGE) {
        uint32_t src_ip;
-       token = strsep(&str, " ");
+       token = skip_blank(&str);
 
        if (!token) {
            return -1;
@@ -285,7 +294,7 @@ static int parse_route_str(char * str, struct v3_vnet_route * route) {
 
        // Figure out Link Here
        if (in4_pton(token, strlen(token), (uint8_t *)&(src_ip), '\0', NULL) != 1) {
-           printk("Invalid SRC IP address (%s)\n", token);
+           WARNING("Invalid SRC IP address (%s)\n", token);
            return -EFAULT;
        }
 
@@ -293,24 +302,24 @@ static int parse_route_str(char * str, struct v3_vnet_route * route) {
        if (link != NULL){
            route->src_id = link->idx;
        }else{
-           printk("can not find src link %s\n", token);
+           WARNING("can not find src link %s\n", token);
            return -1;
        }
     } else if(route->src_type == LINK_INTERFACE){
        uint8_t mac[ETH_ALEN];
        
        if(str2mac(token, mac) == -1){
-          printk("wrong MAC format (%s)\n", token);
+          WARNING("wrong MAC format (%s)\n", token);
           return -1;
        }
           
        route->src_id = v3_vnet_find_dev(mac);
        if (route->src_id == -1){
-           printk("can not find dst device %s\n", token);
+           WARNING("can not find dst device %s\n", token);
            return -1;
        }               
     } else {
-       printk("Invalid link type\n");
+       WARNING("Invalid link type\n");
        return -1;
     }
 
@@ -413,13 +422,13 @@ static int route_seq_show(struct seq_file * s, void * v) {
            break;
        case MAC_NOT:
            seq_printf(s, "not-%x:%x:%x:%x:%x:%x ", 
-                      route->src_mac[0], route->src_mac[1], route->src_mac[2],
-                      route->src_mac[3], route->src_mac[4], route->src_mac[5]);
+                      route->dst_mac[0], route->dst_mac[1], route->dst_mac[2],
+                      route->dst_mac[3], route->dst_mac[4], route->dst_mac[5]);
            break;
        default:
            seq_printf(s, "%x:%x:%x:%x:%x:%x ", 
-                      route->src_mac[0], route->src_mac[1], route->src_mac[2],
-                      route->src_mac[3], route->src_mac[4], route->src_mac[5]);
+                      route->dst_mac[0], route->dst_mac[1], route->dst_mac[2],
+                      route->dst_mac[3], route->dst_mac[4], route->dst_mac[5]);
            break;
     }
 
@@ -535,12 +544,12 @@ static int inject_route(struct vnet_route_iter * route) {
     
     route->idx = v3_vnet_add_route(route->route);
 
-    spin_lock_irqsave(&(vnet_ctrl_s.lock), flags);
+    palacios_spinlock_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);
+    palacios_spinlock_unlock_irqrestore(&(vnet_ctrl_s.lock), flags);
 
-    printk("VNET Control: One route added to VNET core\n");
+    INFO("VNET Control: One route added to VNET core\n");
 
     return 0;
 }
@@ -551,14 +560,14 @@ static void delete_route(struct vnet_route_iter * route) {
 
     v3_vnet_del_route(route->idx);
 
-    spin_lock_irqsave(&(vnet_ctrl_s.lock), flags);
+    palacios_spinlock_lock_irqsave(&(vnet_ctrl_s.lock), flags);
     list_del(&(route->node));
     vnet_ctrl_s.num_routes --;
-    spin_unlock_irqrestore(&(vnet_ctrl_s.lock), flags);
+    palacios_spinlock_unlock_irqrestore(&(vnet_ctrl_s.lock), flags);
 
-    printk("VNET Control: Route %d deleted from VNET\n", route->idx);
+    INFO("VNET Control: Route %d deleted from VNET\n", route->idx);
 
-    kfree(route);
+    palacios_free(route);
     route = NULL;
 }
 
@@ -596,32 +605,35 @@ route_write(struct file * file,
     }
 
     route_buf[size] = '\0';
-    printk("Route written: %s\n", route_buf);
+    INFO("Route written: %s\n", route_buf);
 
-    while ((buf_iter = strsep(&line_str, "\r\n"))) {
+    while ((buf_iter = skip_lines(&line_str))) {
 
-       token = strsep(&buf_iter, " ");
+       token = skip_blank(&buf_iter);
        if (!token) {
            return -EFAULT;
        }
        
        if (strnicmp("ADD", token, strlen("ADD")) == 0) {
            struct vnet_route_iter * new_route = NULL;
-           new_route = kmalloc(sizeof(struct vnet_route_iter), GFP_KERNEL);
+           new_route = palacios_alloc(sizeof(struct vnet_route_iter));
            
            if (!new_route) {
+               ERROR("Cannot allocate new route\n");
                return -ENOMEM;
            }
            
            memset(new_route, 0, sizeof(struct vnet_route_iter));
            
            if (parse_route_str(buf_iter, &(new_route->route)) == -1) {
-               kfree(new_route);
+               ERROR("Cannot parse new route\n");
+               palacios_free(new_route);
                return -EFAULT;
            }
            
            if (inject_route(new_route) != 0) {
-               kfree(new_route);
+               ERROR("Cannot inject new route\n");
+               palacios_free(new_route);
                return -EFAULT;
            }
        } else if (strnicmp("DEL", token, strlen("DEL")) == 0) {
@@ -629,16 +641,16 @@ route_write(struct file * file,
            uint32_t d_idx;
            struct vnet_route_iter * route = NULL;
 
-           idx_str = strsep(&buf_iter, " ");
+           idx_str = skip_blank(&buf_iter);
            
            if (!idx_str) {
-               printk("Missing route idx in DEL Route command\n");
+               WARNING("Missing route idx in DEL Route command\n");
                return -EFAULT;
            }
 
            d_idx = simple_strtoul(idx_str, &idx_str, 10);
 
-           printk("VNET: deleting route %d\n", d_idx);
+           INFO("VNET: deleting route %d\n", d_idx);
 
            list_for_each_entry(route, &(vnet_ctrl_s.route_list), node) {
                if (route->idx == d_idx) {
@@ -647,7 +659,7 @@ route_write(struct file * file,
                }
            }
        } else {
-           printk("Invalid Route command string\n");
+           WARNING("Invalid Route command string\n");
        }
     }
 
@@ -660,28 +672,28 @@ static void delete_link(struct vnet_link_iter * link){
 
     vnet_brg_delete_link(link->idx);
 
-    spin_lock_irqsave(&(vnet_ctrl_s.lock), flags);
+    palacios_spinlock_lock_irqsave(&(vnet_ctrl_s.lock), flags);
     list_del(&(link->node));
     vnet_ctrl_s.num_links --;
-    spin_unlock_irqrestore(&(vnet_ctrl_s.lock), flags);
+    palacios_spinlock_unlock_irqrestore(&(vnet_ctrl_s.lock), flags);
 
-    kfree(link);
+    palacios_free(link);
     link = NULL;
 }
 
 
 static void deinit_links_list(void){
-    struct vnet_link_iter * link;
+    struct vnet_link_iter * link, * tmp_link;
 
-    list_for_each_entry(link, &(vnet_ctrl_s.link_iter_list), node) {
+    list_for_each_entry_safe(link, tmp_link, &(vnet_ctrl_s.link_iter_list), node) {
        delete_link(link);
     }
 }
 
 static void deinit_routes_list(void){
-   struct vnet_route_iter * route;
+   struct vnet_route_iter * route, * tmp_route;
 
-   list_for_each_entry(route, &(vnet_ctrl_s.route_list), node) {
+   list_for_each_entry_safe(route, tmp_route, &(vnet_ctrl_s.route_list), node) {
        delete_route(route);
    }
 }
@@ -703,11 +715,12 @@ link_write(struct file * file, const char * buf, size_t size, loff_t * ppos) {
        return -EFAULT;
     }
 
-    while ((link_iter = strsep(&line_str, "\r\n"))) {
-       printk("Link written: %s\n", link_buf);
-       
-       token = strsep(&link_iter, " ");
+    link_buf[size] = '\0';
+    INFO("Link written: %s\n", link_buf);
+
+    while ((link_iter = skip_lines(&line_str))) {
        
+       token = skip_blank(&link_iter);
        if (!token) {
            return -EFAULT;
        }
@@ -721,15 +734,15 @@ link_write(struct file * file, const char * buf, size_t size, loff_t * ppos) {
            int link_idx;
            unsigned long flags;
            
-           ip_str = strsep(&link_iter, " ");
+           ip_str = skip_blank(&link_iter);
            
            if ((!ip_str) || (!link_iter)) {
-               printk("Missing fields in ADD Link command\n");
+               WARNING("Missing fields in ADD Link command\n");
                return -EFAULT;
            }
            
            if (in4_pton(ip_str, strlen(ip_str), (uint8_t *)&(d_ip), '\0', NULL) != 1) {
-               printk("Invalid Dst IP address (%s)\n", ip_str);
+               WARNING("Invalid Dst IP address (%s)\n", ip_str);
                return -EFAULT;
            }
 
@@ -738,11 +751,16 @@ link_write(struct file * file, const char * buf, size_t size, loff_t * ppos) {
 
            link_idx = vnet_brg_add_link(d_ip, d_port, d_proto);
            if(link_idx < 0){
-               printk("VNET Control: Failed to create link\n");
+               WARNING("VNET Control: Failed to create link\n");
+               return -EFAULT;
+           }
+
+           link = palacios_alloc(sizeof(struct vnet_link_iter));
+           if (!link) {
+               WARNING("VNET Control: Cannot allocate link\n");
                return -EFAULT;
            }
 
-           link = kmalloc(sizeof(struct vnet_link_iter), GFP_KERNEL);
            memset(link, 0, sizeof(struct vnet_link_iter));
 
            link->dst_ip = d_ip;
@@ -750,28 +768,37 @@ link_write(struct file * file, const char * buf, size_t size, loff_t * ppos) {
            link->proto = d_proto;
            link->idx = link_idx;
 
-           spin_lock_irqsave(&(vnet_ctrl_s.lock), flags);
+           palacios_spinlock_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);
+           palacios_spinlock_unlock_irqrestore(&(vnet_ctrl_s.lock), flags);
        } else if (strnicmp("DEL", token, strlen("DEL")) == 0) {
            char * idx_str = NULL;
            uint32_t d_idx;
+           struct vnet_link_iter * link = NULL;
            
-           idx_str = strsep(&link_iter, " ");
+           idx_str = skip_blank(&link_iter);
            
            if (!idx_str) {
-               printk("Missing link idx in DEL Link command\n");
+               WARNING("Missing link idx in DEL Link command\n");
                return -EFAULT;
            }
 
            d_idx = simple_strtoul(idx_str, &idx_str, 10);
 
-           vnet_brg_delete_link(d_idx);
-               
-           printk("VNET Control: One link deleted\n");         
+           INFO("VNET: deleting link %d\n", d_idx);
+
+           list_for_each_entry(link, &(vnet_ctrl_s.link_iter_list), node) {
+               if (link->idx == d_idx) {
+                   delete_link(link);
+                   break;
+               }
+           }
+
+           DEBUG("VNET Control: One link deleted\n");          
+
        } else {
-           printk("Invalid Link command string\n");
+           WARNING("Invalid Link command string\n");
        }
     }
 
@@ -814,10 +841,10 @@ debug_write(struct file * file, const char * buf, size_t size, loff_t * ppos) {
        return -EFAULT;
     }
 
-    in_iter = strsep(&line_str, "\r\n");
+    in_iter = skip_lines(&line_str);
     level = simple_strtol(in_iter, &in_iter, 10);
 
-    printk("VNET Control: Set VNET Debug level to %d\n", level);
+    DEBUG("VNET Control: Set VNET Debug level to %d\n", level);
 
     if(level >= 0){
        net_debug = level;
@@ -891,39 +918,40 @@ static int init_proc_files(void) {
     struct proc_dir_entry * debug_entry = NULL;
     struct proc_dir_entry * vnet_root = NULL;
 
-    vnet_root = proc_mkdir("vnet", NULL);
+
+    vnet_root = proc_mkdir("vnet", palacios_get_procdir());
+
     if (vnet_root == NULL) {
        return -1;
     }
 
-    route_entry = create_proc_entry("routes", 0, vnet_root);
+    
+    PAL_PROC_CREATE(route_entry,"routes",0644, vnet_root,&route_fops);
+
     if (route_entry == NULL) {
        remove_proc_entry("vnet", NULL);
        return -1;
     }
-    route_entry->proc_fops = &route_fops;
        
+    PAL_PROC_CREATE(link_entry,"links", 0644, vnet_root,&link_fops);
 
-    link_entry = create_proc_entry("links", 0, vnet_root);
     if (link_entry == NULL) {
        remove_proc_entry("routes", vnet_root);
        remove_proc_entry("vnet", NULL);
        return -1;
     }
-    link_entry->proc_fops = &link_fops;
-       
 
-    stat_entry = create_proc_entry("stats", 0, vnet_root);
+    PAL_PROC_CREATE(stat_entry,"stats", 0644, vnet_root, &stat_fops);
+
     if(stat_entry == NULL) {
        remove_proc_entry("links", vnet_root);
        remove_proc_entry("routes", vnet_root);
        remove_proc_entry("vnet", NULL);
        return -1;
     }
-    stat_entry->proc_fops = &stat_fops;
 
+    PAL_PROC_CREATE(debug_entry,"debug", 0644, vnet_root,&debug_fops);
 
-    debug_entry = create_proc_entry("debug", 0, vnet_root);
     if(debug_entry == NULL) {
        remove_proc_entry("links", vnet_root);
        remove_proc_entry("routes", vnet_root);
@@ -931,7 +959,6 @@ static int init_proc_files(void) {
        remove_proc_entry("vnet", NULL);
        return -1;
     }
-    debug_entry->proc_fops = &debug_fops;
 
     vnet_ctrl_s.vnet_proc_root = vnet_root;
 
@@ -946,7 +973,7 @@ static void destroy_proc_files(void) {
     remove_proc_entry("links", vnet_root);
     remove_proc_entry("routes", vnet_root);
     remove_proc_entry("stats", vnet_root);
-    remove_proc_entry("vnet", NULL);   
+    remove_proc_entry("vnet", palacios_get_procdir()); 
 }
 
 
@@ -960,23 +987,30 @@ int vnet_ctrl_init(void) {
 
     INIT_LIST_HEAD(&(vnet_ctrl_s.link_iter_list));
     INIT_LIST_HEAD(&(vnet_ctrl_s.route_list));
-    spin_lock_init(&(vnet_ctrl_s.lock));
+    palacios_spinlock_init(&(vnet_ctrl_s.lock));
 
     init_proc_files();
        
-    printk("VNET Linux control module initiated\n");
+    NOTICE("VNET Linux control module initiated\n");
 
     return 0;
 }
 
 
 void vnet_ctrl_deinit(void){
+    
+    INFO("VNET Control Deinit Started\n");
+
     destroy_proc_files();
 
     deinit_links_list();
     deinit_routes_list();
 
     vnet_ctrl_s.status = 0;
+
+    palacios_spinlock_deinit(&(vnet_ctrl_s.lock));
+
+    INFO("VNET Control Deinit Finished\n");
 }