-/*
- * 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>
#include <vnet/vnet.h>
#include <vnet/vnet_hashtable.h>
#include "palacios-vnet.h"
+#include "palacios.h"
#define VNET_SERVER_PORT 9000
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){
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;
}
}
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;
}
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);
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) {
// 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;
}
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;
}
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;
} 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;
}
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;
// 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;
}
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;
}
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;
}
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;
}
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;
}
}
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) {
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) {
}
}
} else {
- printk("Invalid Route command string\n");
+ WARNING("Invalid Route command string\n");
}
}
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);
}
}
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;
}
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;
}
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;
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");
}
}
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;
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);
+ route_entry = create_proc_entry("routes", 0644, vnet_root);
if (route_entry == NULL) {
remove_proc_entry("vnet", NULL);
return -1;
route_entry->proc_fops = &route_fops;
- link_entry = create_proc_entry("links", 0, vnet_root);
+ link_entry = create_proc_entry("links", 0644, vnet_root);
if (link_entry == NULL) {
remove_proc_entry("routes", vnet_root);
remove_proc_entry("vnet", NULL);
link_entry->proc_fops = &link_fops;
- stat_entry = create_proc_entry("stats", 0, vnet_root);
+ stat_entry = create_proc_entry("stats", 0644, vnet_root);
if(stat_entry == NULL) {
remove_proc_entry("links", vnet_root);
remove_proc_entry("routes", vnet_root);
stat_entry->proc_fops = &stat_fops;
- debug_entry = create_proc_entry("debug", 0, vnet_root);
+ debug_entry = create_proc_entry("debug", 0644, vnet_root);
if(debug_entry == NULL) {
remove_proc_entry("links", vnet_root);
remove_proc_entry("routes", 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);
+ remove_proc_entry("vnet", palacios_get_procdir());
}
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");
}