From: Lei Xia Date: Sun, 22 May 2011 03:21:03 +0000 (-0500) Subject: add missed file X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?p=palacios.git;a=commitdiff_plain;h=537212e255e59b086004e0eb156a31d248dd7508 add missed file --- diff --git a/linux_module/palacios-vnet-brg.c b/linux_module/palacios-vnet-brg.c new file mode 100644 index 0000000..e87d422 --- /dev/null +++ b/linux_module/palacios-vnet-brg.c @@ -0,0 +1,520 @@ +/* + Palacios VNET Host Bridge + (c) Lei Xia, 2010 + */ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#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; +} + + diff --git a/linux_module/palacios-vnet-bridge.c b/linux_module/palacios-vnet-bridge.c deleted file mode 100644 index 0b0ee4f..0000000 --- a/linux_module/palacios-vnet-bridge.c +++ /dev/null @@ -1,1293 +0,0 @@ -/* - Palacios VNET Host Bridge - (c) Lei Xia, 2010 - */ -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include "palacios-vnet.h" - -#define VNET_SERVER_PORT 9000 - -struct palacios_vnet_route { - struct v3_vnet_route route; - - int idx; - - struct list_head node; -}; - -typedef enum {UDP, TCP, RAW, NONE} vnet_bridge_proto_t; - -struct vnet_link { - 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 idx; - - struct list_head node; -}; - - -struct palacios_vnet_state { - uint32_t num_routes; - uint32_t num_links; - uint32_t route_idx; - uint32_t link_idx; - - uint8_t status; - - struct list_head route_list; - struct list_head link_list; - - struct hashtable *ip2link; /* map IP to its Link */ - - 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; - - struct proc_dir_entry * vnet_proc_root; - - unsigned int pkt_from_vmm, pkt_to_vmm, pkt_drop_vmm; - unsigned int pkt_from_phy, pkt_to_phy, pkt_drop_phy; -}; - - -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->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->idx == idx) { - return route; - } - } - - return NULL; -} - - -static int parse_mac_str(char * str, uint8_t * qual, uint8_t * mac) { - char * token; - - printk("Parsing MAC (%s)\n", str); - - *qual = MAC_NOSET; - if(strnicmp("any", str, strlen(str)) == 0){ - *qual = MAC_ANY; - return 0; - }else if(strnicmp("none", str, strlen(str)) == 0){ - *qual = MAC_NONE; - return 0; - }else{ - if (strstr(str, "-")) { - token = strsep(&str, "-"); - - if (strnicmp("not", token, strlen("not")) == 0) { - *qual = MAC_NOT; - } else { - printk("Invalid MAC String token (%s)\n", token); - return -1; - } - } - - if (strstr(str, ":")) { - int i = 0; - - if(*qual == MAC_NOSET){ - *qual = MAC_ADDR; - } - - for (i = 0; i < 6; i++) { - token = strsep(&str, ":"); - if (!token) { - printk("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]); - - }else { - printk("Invalid MAC String token (%s)\n", token); - return -1; - } - - } - - return 0; -} - - -static int str2mac(char * str, uint8_t * mac){ - int i = 0; - char *hex = NULL; - - for (i = 0; i < ETH_ALEN; i++) { - hex = strsep(&str, ":"); - if (!hex) { - printk("Invalid MAC String token (%s)\n", str); - return -1; - } - mac[i] = simple_strtol(hex, &hex, 16); - } - - return 0; -} - - -/* 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 int parse_route_str(char * str, struct v3_vnet_route * route) { - char * token = NULL; - struct vnet_link *link = NULL; - - // src MAC - token = strsep(&str, " "); - if (!token) { - return -1; - } - parse_mac_str(token, &(route->src_mac_qual), route->src_mac); - - // dst MAC - token = strsep(&str, " "); - if (!token) { - return -1; - } - parse_mac_str(token, &(route->dst_mac_qual), route->dst_mac); - - // dst LINK type - token = strsep(&str, " "); - if (!token) { - return -1; - } - printk("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); - return -1; - } - - // dst link - token = strsep(&str, " "); - if (!token) { - return -1; - } - printk("dst ID=(%s)\n", token); - - // Figure out link here - if (route->dst_type == LINK_EDGE) { - uint32_t link_ip; - - // 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); - return -EFAULT; - } - - link = link_by_ip(link_ip); - if (link != NULL){ - 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->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); - return -1; - } - - route->dst_id = v3_vnet_find_dev(mac); - if (route->dst_id == -1){ - printk("can not find dst device %s\n", token); - return -1; - } - } else { - printk("Unsupported dst link type\n"); - return -1; - } - - route->src_id = -1; - route->src_type = -1; - - // src LINK - token = strsep(&str, " "); - - printk("SRC type = %s\n", token); - - if (!token) { - return -1; - } - - if (strnicmp("interface", token, strlen("interface")) == 0) { - route->src_type = LINK_INTERFACE; - } else if (strnicmp("edge", token, strlen("edge")) == 0) { - route->src_type = LINK_EDGE; - } else if (strnicmp("any", token, strlen("any")) == 0) { - route->src_type = LINK_ANY; - } else { - printk("Invalid Src link type (%s)\n", token); - return -1; - } - - - if (route->src_type == LINK_ANY) { - route->src_id = -1; - } else if (route->src_type == LINK_EDGE) { - uint32_t src_ip; - token = strsep(&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); - return -EFAULT; - } - - link = link_by_ip(src_ip); - if (link != NULL){ - route->src_id = link->idx; - }else{ - printk("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); - return -1; - } - - route->src_id = v3_vnet_find_dev(mac); - if (route->src_id == -1){ - printk("can not find dst device %s\n", token); - return -1; - } - } else { - printk("Invalid link type\n"); - return -1; - } - - return 0; -} - - - - -static void * route_seq_start(struct seq_file * s, loff_t * pos) { - struct palacios_vnet_route * route_iter = NULL; - loff_t i = 0; - - - if (*pos >= vnet_state.num_routes) { - return NULL; - } - - list_for_each_entry(route_iter, &(vnet_state.route_list), node) { - - if (i == *pos) { - break; - } - - i++; - } - - return route_iter; -} - - -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; - - route_iter = list_entry(((struct palacios_vnet_route *)v)->node.next, struct palacios_vnet_route, node); - - // Check if the list has looped - if (&(route_iter->node) == &(vnet_state.route_list)) { - return NULL; - } - - *pos += 1; - - return route_iter; -} - - -static void * link_seq_next(struct seq_file * s, void * v, loff_t * pos) { - struct vnet_link * link_iter = NULL; - - - link_iter = list_entry(((struct vnet_link *)v)->node.next, struct vnet_link, node); - - // Check if the list has looped - if (&(link_iter->node) == &(vnet_state.link_list)) { - return NULL; - } - - *pos += 1; - - return link_iter; -} - - -static void route_seq_stop(struct seq_file * s, void * v) { - - return; -} - - -static void link_seq_stop(struct seq_file * s, void * v) { - - return; -} - -static int route_seq_show(struct seq_file * s, void * v) { - struct palacios_vnet_route * route_iter = v; - struct v3_vnet_route * route = &(route_iter->route); - - seq_printf(s, "%d:\t", route_iter->idx); - - seq_printf(s, "\nSrc:\t"); - switch (route->src_mac_qual) { - case MAC_ANY: - seq_printf(s, "any "); - break; - case MAC_NONE: - seq_printf(s, "none "); - break; - case MAC_NOT: - seq_printf(s, "not-%2x:%2x:%2x:%2x:%2x:%2x ", - route->src_mac[0], route->src_mac[1], route->src_mac[2], - route->src_mac[3], route->src_mac[4], route->src_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]); - break; - } - - seq_printf(s, "\nDst:\t"); - switch (route->dst_mac_qual) { - case MAC_ANY: - seq_printf(s, "any "); - break; - case MAC_NONE: - seq_printf(s, "none "); - 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]); - 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]); - break; - } - - 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); - seq_printf(s, "EDGE %pI4", &link->dst_ip); - break; - } - case LINK_INTERFACE: { - seq_printf(s, "INTERFACE "); - seq_printf(s, "%d ", route->dst_id); - break; - } - default: - seq_printf(s, "Invalid Dst Link Type (%d) ", route->dst_type); - break; - } - - 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); - seq_printf(s, "EDGE %pI4", &link->dst_ip); - break; - } - case LINK_INTERFACE: { - seq_printf(s, "INTERFACE %d", route->src_id); - break; - } - case LINK_ANY: - seq_printf(s, "ANY"); - break; - default: - seq_printf(s, "Invalid Src Link Type (%d) ", route->src_type); - break; - } - - - seq_printf(s, "\n"); - - return 0; -} - - -static int link_seq_show(struct seq_file * s, void * v) { - struct vnet_link * link_iter = v; - - 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->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); - - return 0; -} - - -static struct seq_operations route_seq_ops = { - .start = route_seq_start, - .next = route_seq_next, - .stop = route_seq_stop, - .show = route_seq_show -}; - - -static struct seq_operations link_seq_ops = { - .start = link_seq_start, - .next = link_seq_next, - .stop = link_seq_stop, - .show = link_seq_show -}; - - -static int route_open(struct inode * inode, struct file * file) { - return seq_open(file, &route_seq_ops); -} - - -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)); - vnet_state.num_routes++; - route->idx = vnet_state.route_idx ++; - spin_unlock_irqrestore(&(vnet_state.lock), flags); - - printk("Palacios-vnet: One route added to VNET core\n"); - - return 0; -} - - -static int delete_route(struct palacios_vnet_route * route) { - unsigned long flags; - - //v3_vnet_del_route(route->route); - - spin_lock_irqsave(&(vnet_state.lock), flags); - list_del(&(route->node)); - vnet_state.num_routes --; - spin_unlock_irqrestore(&(vnet_state.lock), flags); - - printk("Palacios-vnet: Route %d deleted from VNET\n", route->idx); - - kfree(route); - - return 0; -} - -static ssize_t -route_write(struct file * file, - const char * buf, - size_t size, - loff_t * ppos) { - char route_buf[256]; - char * buf_iter = NULL; - char * line_str = route_buf; - char * token = NULL; - - if (size >= 256) { - return -EFAULT; - } - - if (copy_from_user(route_buf, buf, size)) { - return -EFAULT; - } - - route_buf[size] = '\0'; - printk("Route written: %s\n", route_buf); - - while ((buf_iter = strsep(&line_str, "\r\n"))) { - - token = strsep(&buf_iter, " "); - if (!token) { - return -EFAULT; - } - - if (strnicmp("ADD", token, strlen("ADD")) == 0) { - struct palacios_vnet_route * new_route = NULL; - new_route = kmalloc(sizeof(struct palacios_vnet_route), GFP_KERNEL); - - if (!new_route) { - return -ENOMEM; - } - - memset(new_route, 0, sizeof(struct palacios_vnet_route)); - - if (parse_route_str(buf_iter, &(new_route->route)) == -1) { - kfree(new_route); - return -EFAULT; - } - - 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"); - } else { - printk("Invalid Route command string\n"); - } - } - - return size; -} - - -static void delete_link(struct vnet_link * link){ - unsigned long flags; - - link->sock->ops->release(link->sock); - - spin_lock_irqsave(&(vnet_state.lock), flags); - list_del(&(link->node)); - vnet_htable_remove(vnet_state.ip2link, (addr_t)&(link->dst_ip), 0); - vnet_state.num_links --; - spin_unlock_irqrestore(&(vnet_state.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; -} - - -static void deinit_links_list(void){ - struct vnet_link * link; - - list_for_each_entry(link, &(vnet_state.link_list), node) { - delete_link(link); - } -} - -static void deinit_routes_list(void){ - struct palacios_vnet_route * route; - - list_for_each_entry(route, &(vnet_state.route_list), node) { - delete_route(route); - } -} - - - -static int 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_state.lock), flags); - list_add(&(link->node), &(vnet_state.link_list)); - vnet_state.num_links ++; - link->idx = vnet_state.link_idx ++; - vnet_htable_insert(vnet_state.ip2link, (addr_t)&(link->dst_ip), (addr_t)link); - spin_unlock_irqrestore(&(vnet_state.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 0; -} - - -/* ADD dst-ip 9000 [udp|tcp] */ -static ssize_t -link_write(struct file * file, const char * buf, size_t size, loff_t * ppos) { - char link_buf[256]; - char * link_iter = NULL; - char * line_str = link_buf; - char * token = NULL; - - if (size >= 256) { - return -EFAULT; - } - - if (copy_from_user(link_buf, buf, size)) { - return -EFAULT; - } - - while ((link_iter = strsep(&line_str, "\r\n"))) { - printk("Link written: %s\n", link_buf); - - token = strsep(&link_iter, " "); - - if (!token) { - return -EFAULT; - } - - if (strnicmp("ADD", token, strlen("ADD")) == 0) { - struct vnet_link * new_link = NULL; - char * ip_str = NULL; - uint32_t ip; - - ip_str = strsep(&link_iter, " "); - - if ((!ip_str) || (!link_iter)) { - printk("Missing fields in ADD Link command\n"); - return -EFAULT; - } - - if (in4_pton(ip_str, strlen(ip_str), (uint8_t *)&(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; - } - - memset(new_link, 0, sizeof(struct vnet_link)); - - new_link->dst_ip = ip; - new_link->dst_port = simple_strtol(link_iter, &link_iter, 10); - - //TODO: Parse UDP|TCP - new_link->sock_proto = UDP; - - if (create_link(new_link) != 0) { - printk("Could not create link\n"); - kfree(new_link); - return -EFAULT; - } - - } else if (strnicmp("DEL", token, strlen("DEL")) == 0) { - printk("Link deletion not supported\n"); - } else { - printk("Invalid Link command string\n"); - } - } - - return size; -} - - -static struct file_operations route_fops = { - .owner = THIS_MODULE, - .open = route_open, - .read = seq_read, - .write = route_write, - .llseek = seq_lseek, - .release = seq_release -}; - - -static struct file_operations link_fops = { - .owner = THIS_MODULE, - .open = link_open, - .read = seq_read, - .write = link_write, - .llseek = seq_lseek, - .release = seq_release -}; - - -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; - int level = -1; - - if (size >= 32) { - return -EFAULT; - } - - if (copy_from_user(link_buf, buf, size)) { - return -EFAULT; - } - - link_iter = strsep(&line_str, "\r\n"); - level = simple_strtol(link_iter, &link_iter, 10); - - printk("Set VNET Debug level to %d\n", level); - - if(level >= 0){ - net_debug = level; - } - - return size; -} - - -static int debug_show(struct seq_file * file, void * v){ - seq_printf(file, "Current VNET Debug Level: %d\n", net_debug); - - return 0; -} - -static int debug_open(struct inode * inode, struct file * file) { - return single_open(file, debug_show, NULL); -} - -static struct file_operations debug_fops = { - .owner = THIS_MODULE, - .open = debug_open, - .read = seq_read, - .write = debug_write, - .llseek = seq_lseek, - .release = seq_release -}; - -static int stat_show(struct seq_file * file, void * v){ - struct vnet_stat stats; - - v3_vnet_stat(&stats); - - seq_printf(file, "VNET Core\n"); - seq_printf(file, "\tReceived Packets: %d\n", stats.rx_pkts); - seq_printf(file, "\tReceived Bytes: %lld\n", stats.rx_bytes); - seq_printf(file, "\tTransmitted Packets: %d\n", stats.tx_pkts); - seq_printf(file, "\tTransmitted Bytes: %lld\n", stats.tx_bytes); - - - 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); - - return 0; -} - -static int stat_open(struct inode * inode, struct file * file) { - return single_open(file, stat_show, NULL); -} - -static struct file_operations stat_fops = { - .owner = THIS_MODULE, - .open = stat_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release -}; - - -static int init_proc_files(void) { - struct proc_dir_entry * route_entry = NULL; - struct proc_dir_entry * link_entry = NULL; - struct proc_dir_entry * stat_entry = NULL; - struct proc_dir_entry * debug_entry = NULL; - struct proc_dir_entry * vnet_root = NULL; - - vnet_root = proc_mkdir("vnet", NULL); - if (vnet_root == NULL) { - return -1; - } - - route_entry = create_proc_entry("routes", 0, 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); - 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); - 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; - - - 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); - remove_proc_entry("stats", vnet_root); - remove_proc_entry("vnet", NULL); - return -1; - } - debug_entry->proc_fops = &debug_fops; - - vnet_state.vnet_proc_root = vnet_root; - - return 0; -} - - -static void destroy_proc_files(void) { - struct proc_dir_entry * vnet_root = vnet_state.vnet_proc_root; - - 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 -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_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(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_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 ++; - } - - 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; - - 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; -} - -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->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_bridge(void) { - struct v3_vnet_bridge_ops bridge_ops; - - - if(vnet_state.status != 0) { - return -1; - } - vnet_state.status = 1; - - memset(&vnet_state, 0, sizeof(struct palacios_vnet_state)); - - INIT_LIST_HEAD(&(vnet_state.link_list)); - INIT_LIST_HEAD(&(vnet_state.route_list)); - spin_lock_init(&(vnet_state.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; - } - - vnet_state.serv_thread = kthread_run(vnet_server, NULL, "vnet-server"); - - 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"); - - return 0; -} - - -void palacios_deinit_vnet_bridge(void){ - - destroy_proc_files(); - - //v3_vnet_delete_bridge(NULL, &bridge_ops, HOST_LNX_BRIDGE, NULL); - kthread_stop(vnet_state.serv_thread); - vnet_state.serv_sock->ops->release(vnet_state.serv_sock); - - deinit_links_list(); - deinit_routes_list(); - - vnet_free_htable(vnet_state.ip2link, 0, 0); - - vnet_state.status = 0; -} - -