From: Lei Xia Date: Wed, 17 Nov 2010 18:58:10 +0000 (-0600) Subject: VNET code clean and rearrangement X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?p=palacios.git;a=commitdiff_plain;h=b6844af8df260e609bee254bbe58128d0e8fc010 VNET code clean and rearrangement --- diff --git a/Kconfig b/Kconfig index bb241ee..4f899fe 100644 --- a/Kconfig +++ b/Kconfig @@ -161,13 +161,6 @@ config DEBUG_VNET help Enable the Vnet debug in Palacios -config VNET_PROFILE - depends on EXPERIMENTAL && VNET - bool "Enable Vnet Profiling in Palacios" - default n - help - Enable the Vnet performance profiling in Palacios - config LINUX_VIRTIO_VNET bool "Enable Virtio VNET interface" default n @@ -182,20 +175,6 @@ config DEBUG_LINUX_VIRTIO_VNET help Enable debugging for the VNET Virtio Device -config LINUX_VNET_BRIDGE - bool "Enable VNET Bridge for Linux host" - default n - depends on PCI && EXPERIMENTAL && VNET && LINUX - help - Enable the VNET Bridge for Linux host - -config DEBUG_LINUX_VNET_BRIDGE - bool "VNET Host Linux Bridge Debug" - default n - depends on LINUX_VNET_BRIDGE && DEBUG_ON && LINUX - help - Enable debugging for the VNET Host Linux Bridge - endmenu diff --git a/palacios/include/palacios/vmm_vnet.h b/palacios/include/palacios/vmm_vnet.h index d990880..b8a2d00 100644 --- a/palacios/include/palacios/vmm_vnet.h +++ b/palacios/include/palacios/vmm_vnet.h @@ -26,18 +26,20 @@ #include - -#define V3_VNET_POLLING_VECTOR 50 - typedef enum {MAC_ANY=0, MAC_NOT, MAC_NONE, MAC_ADDR} mac_type_t; //for 'src_mac_qual' and 'dst_mac_qual' typedef enum {LINK_INTERFACE=0, LINK_EDGE, LINK_ANY} link_type_t; //for 'type' and 'src_type' in struct routing - #define VNET_HASH_SIZE 17 #define ETHERNET_HEADER_LEN 14 #define ETHERNET_MTU 1500 #define ETHERNET_PACKET_LEN (ETHERNET_HEADER_LEN + ETHERNET_MTU) +#define VMM_DRIVERN 1 +#define GUEST_DRIVERN 0 + +#define HOST_LNX_BRIDGE 1 +#define CTL_VM_BRIDGE 2 + //routing table entry struct v3_vnet_route { uint8_t src_mac[6]; @@ -76,41 +78,11 @@ struct v3_vnet_pkt { } __attribute__((packed)); -#ifdef CONFIG_VNET_PROFILE -struct v3_vnet_profile{ - uint64_t time_copy_from_guest; - uint64_t time_route_lookup; - uint64_t time_mallocfree; - uint64_t time_copy_to_guest; - uint64_t total_handle_time; - uint64_t memcpy_time; - - uint64_t total_exit_time; - bool print; - - uint64_t virtio_handle_start; -}; -#endif - - -struct v3_vnet_bridge_xcall_args{ - struct v3_vm_info * vm; - struct v3_vnet_pkt *vnet_pkts; - uint16_t pkt_num; - void * private_data; -}; - -struct v3_vnet_dev_xcall_args{ - struct v3_vm_info * vm; - void * private_data; -}; - struct v3_vnet_dev_ops { int (*input)(struct v3_vm_info * vm, struct v3_vnet_pkt * pkt, void * dev_data); void (*poll) (struct v3_vm_info * vm, void * dev_data); - void (*poll_xcall)(void *arg); void (*start_tx)(void * dev_data); void (*stop_tx)(void * dev_data); @@ -120,32 +92,23 @@ struct v3_vnet_bridge_ops { int (*input)(struct v3_vm_info * vm, struct v3_vnet_pkt * pkt, void * private_data); - int (*xcall_input)(void * data); - void (*polling_pkt)(struct v3_vm_info * vm, + void (*poll)(struct v3_vm_info * vm, void * private_data); }; - +int v3_init_vnet(); int v3_vnet_send_pkt(struct v3_vnet_pkt * pkt, void *private_data); +void v3_vnet_poll(struct v3_vm_info *vm); int v3_vnet_add_route(struct v3_vnet_route route); - -int v3_init_vnet(); - int v3_vnet_add_bridge(struct v3_vm_info * vm, struct v3_vnet_bridge_ops *ops, + uint8_t type, void * priv_data); - int v3_vnet_add_dev(struct v3_vm_info *info, uint8_t mac[6], struct v3_vnet_dev_ops *ops, void * priv_data); -void v3_vnet_poll(struct v3_vm_info *vm); - -int v3_vnet_enable_device(int dev_id); - -int v3_vnet_disable_device(int dev_id); - #endif #endif diff --git a/palacios/src/devices/lnx_virtio_nic.c b/palacios/src/devices/lnx_virtio_nic.c index ca492fb..3ef9509 100644 --- a/palacios/src/devices/lnx_virtio_nic.c +++ b/palacios/src/devices/lnx_virtio_nic.c @@ -95,10 +95,8 @@ struct virtio_net_state { int buffed_rx; int tx_disabled; /* stop TX pkts from guest */ - uint16_t cur_notify_tx_idx; /*for used in update_tx_queue */ uint64_t pkt_sent, pkt_recv, pkt_drop; - uint64_t tx_stop_times, rx_stop_times, tx_poll_times, rx_ipi_num; struct v3_dev_net_ops * net_ops; v3_lock_t rx_lock, tx_lock; @@ -162,7 +160,7 @@ static int virtio_init_state(struct virtio_net_state * virtio) return 0; } -static int pkt_tx(struct guest_info *core, struct virtio_net_state * virtio, struct vring_desc * buf_desc) +static int pkt_tx(struct guest_info * core, struct virtio_net_state * virtio, struct vring_desc * buf_desc) { uint8_t * buf = NULL; uint32_t len = buf_desc->length; @@ -176,7 +174,7 @@ static int pkt_tx(struct guest_info *core, struct virtio_net_state * virtio, str } -static int copy_data_to_desc(struct guest_info *core, +static int copy_data_to_desc(struct guest_info * core, struct virtio_net_state * virtio_state, struct vring_desc * desc, uchar_t * buf, @@ -217,6 +215,7 @@ static inline void disable_cb(struct virtio_queue *queue) { queue->used->flags |= VRING_NO_NOTIFY_FLAG; } + /* interrupt the guest, so the guest core get EXIT to Palacios * this happens when there are either incoming pkts for the guest * or the guest can start TX pkts again */ @@ -240,20 +239,6 @@ static int handle_rx_kick(struct guest_info *core, struct virtio_net_state * vir return 0; } -#ifdef CONFIG_VNET_PROFILE -static void print_profile_info(struct virtio_net_state *virtio){ - PrintError("Virtio NIC: %p, sent: %lld, rxed: %lld, dropped: %lld, \ - tx_stop: %lld, rx_stop: %lld, poll_time: %lld, rx_ipi: %lld\n", - virtio, - virtio->pkt_sent, - virtio->pkt_recv, - virtio->pkt_drop, - virtio->tx_stop_times, - virtio->rx_stop_times, - virtio->tx_poll_times, - virtio->rx_ipi_num); -} -#endif static int handle_ctrl(struct guest_info *core, struct virtio_net_state * virtio) { @@ -327,24 +312,6 @@ static int handle_pkt_tx(struct guest_info *core, struct virtio_net_state * virt virtio_state->virtio_cfg.pci_isr = 0x1; } - -#ifdef CONFIG_VNET_PROFILE - static long min = 1024, max = 0, total=0; - static int i=0; - total += recved; - i ++; - if(recved > max) max = recved; - if(recved < min) min = recved; - if(total > 100000) { - PrintError("VNIC: TX polling: %ld, min %ld, max %ld, avg: %ld pkts\n", total, min, max, total/i); - min = 1024; - max = 0; - i = 1; - total = 0; - } -#endif - - return 0; exit_error: @@ -642,7 +609,6 @@ static int virtio_rx(uint8_t * buf, uint32_t size, void * private_data) { (q->avail->flags & VIRTIO_NO_IRQ_FLAG)) { if(virtio->virtio_dev->vm->cores[0].cpu_id != V3_Get_CPU()){ notify_guest(virtio); - virtio->rx_ipi_num ++; } virtio->buffed_rx = 0; } @@ -651,8 +617,6 @@ static int virtio_rx(uint8_t * buf, uint32_t size, void * private_data) { /* RX queue is full, tell backend to stop RX on this device */ virtio->net_ops->stop_rx(virtio->backend_data); enable_cb(&virtio->rx_vq); - - virtio->rx_stop_times ++; ret_val = -ERR_VIRTIO_RXQ_FULL; goto exit; @@ -683,48 +647,39 @@ static struct v3_device_ops dev_ops = { /* TODO: Issue here: which vm info it needs? calling VM or the device's own VM? */ -static void virtio_nic_poll(struct v3_vm_info *vm, void *data){ - struct virtio_net_state *virtio = (struct virtio_net_state *)data; +static void virtio_nic_poll(struct v3_vm_info * vm, void * data){ + struct virtio_net_state * virtio = (struct virtio_net_state *)data; handle_pkt_tx(&(vm->cores[0]), virtio); - - virtio->tx_poll_times ++; - -#ifdef CONFIG_VNET_PROFILE - static uint64_t last_time = 0; - uint64_t time; - rdtscll(time); - if((time - last_time) > 5000000000){ - last_time = time; - print_profile_info(virtio); - } -#endif } -static void virtio_start_tx(void *data){ +static void virtio_start_tx(void * data){ struct virtio_net_state * virtio = (struct virtio_net_state *)data; + unsigned long flags; - /* do we need a lock here? */ + flags = v3_lock_irqsave(virtio->tx_lock); virtio->tx_disabled = 0; - /* notify the device's guest it can start sending pkt */ + /* notify the device's guest to start sending pkt */ if(virtio->virtio_dev->vm->cores[0].cpu_id != V3_Get_CPU()){ notify_guest(virtio); } + v3_unlock_irqrestore(virtio->tx_lock, flags); } -static void virtio_stop_tx(void *data){ +static void virtio_stop_tx(void * data){ struct virtio_net_state * virtio = (struct virtio_net_state *)data; + unsigned long flags; - /* do we need a lock here? */ + flags = v3_lock_irqsave(virtio->tx_lock); virtio->tx_disabled = 1; - /* how do we stop the guest to exit to palacios for sending pkt? */ + /* stop the guest to exit to palacios for sending pkt? */ if(virtio->virtio_dev->vm->cores[0].cpu_id != V3_Get_CPU()){ disable_cb(&virtio->tx_vq); } - virtio->tx_stop_times ++; + v3_unlock_irqrestore(virtio->tx_lock, flags); } @@ -797,11 +752,6 @@ static int register_dev(struct virtio_dev_state * virtio, struct virtio_net_stat virtio_init_state(net_state); -#if 0 //temporary hacking LX - vnic_states[num_vnic ++] = net_state; - PrintError("VNIC: num of vnic %d\n", num_vnic); -#endif - return 0; } diff --git a/palacios/src/devices/lnx_virtio_vnet.c b/palacios/src/devices/lnx_virtio_vnet.c index 74164c9..f164855 100644 --- a/palacios/src/devices/lnx_virtio_vnet.c +++ b/palacios/src/devices/lnx_virtio_vnet.c @@ -222,7 +222,9 @@ static int handle_cmd_kick(struct guest_info * core, struct virtio_vnet_state * } -static int vnet_pkt_input_cb(struct v3_vm_info * vm, struct v3_vnet_pkt *pkt, void * private_data){ +static int vnet_pkt_input_cb(struct v3_vm_info * vm, + struct v3_vnet_pkt * pkt, + void * private_data){ struct virtio_vnet_state * vnet_state = (struct virtio_vnet_state *)private_data; struct virtio_queue * q = &(vnet_state->queue[RECV_QUEUE]); int ret_val = -1; @@ -279,17 +281,6 @@ exit: return ret_val; } -static int vnet_pkt_input_xcall(void *data){ - struct v3_vnet_bridge_xcall_args *args = (struct v3_vnet_bridge_xcall_args *)data; - int i = 0; - - for(i = 0; i < args->pkt_num; i++) { - vnet_pkt_input_cb(args->vm, &(args->vnet_pkts[i]), args->private_data); - } - - return 0; -} - static int handle_pkt_kick(struct guest_info *core, struct virtio_vnet_state * vnet_state) { struct virtio_queue * q = &(vnet_state->queue[XMIT_QUEUE]); @@ -658,11 +649,10 @@ static int dev_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) { struct v3_vnet_bridge_ops brg_ops; brg_ops.input = vnet_pkt_input_cb; - brg_ops.polling_pkt = vnet_virtio_poll; - brg_ops.xcall_input = vnet_pkt_input_xcall; + brg_ops.poll = vnet_virtio_poll; V3_Print("Registering Virtio device as vnet bridge\n"); - v3_vnet_add_bridge(vm, &brg_ops, (void *)vnet_state); + v3_vnet_add_bridge(vm, &brg_ops, CTL_VM_BRIDGE, (void *)vnet_state); return 0; } diff --git a/palacios/src/devices/lnx_vnet_brg.c b/palacios/src/devices/lnx_vnet_brg.c deleted file mode 100644 index c4f7272..0000000 --- a/palacios/src/devices/lnx_vnet_brg.c +++ /dev/null @@ -1,249 +0,0 @@ -/* - * 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) 2010, Lei Xia - * Copyright (c) 2010, The V3VEE Project - * All rights reserved. - * - * Author: Lei Xia - * - * This is free software. You are permitted to use, - * redistribute, and modify it as specified in the file "V3VEE_LICENSE". - */ - - /* VNET backend bridge for Linux host - */ -#include -#include -#include -#include -#include -#include - -#ifndef CONFIG_DEBUG_VNET_LNX_BRIGE -#undef PrintDebug -#define PrintDebug(fmt, args...) -#endif - -typedef enum {SOCK_UDP, SOCK_TCP, SOCK_OTHER} sock_type_t; - -const uint16_t vnet_udp_port = 20003; - -struct vnet_link { - uint32_t dst_ip; - uint16_t dst_port; - - int socket; - sock_type_t type; - - int link_idx; - - struct list_head node; -}; - -struct vnet_brg_state { - uint32_t num_links; - struct list_head link_list; - - int serv_sock; - sock_type_t serv_sock_type; - int serv_port; - - v3_lock_t lock; - - unsigned long pkt_sent, pkt_recv, pkt_drop; -}; - - -static int vnet_lnxbrg_reset(struct vnet_brg_state * state) { - memset(state, 0, sizeof(struct vnet_brg_state)); - - state->num_links = 0; - state->serv_sock = -1; - state->serv_port = vnet_udp_port; - state->serv_sock_type = SOCK_UDP; - - if(v3_lock_init(&(state->lock)) < 0){ - PrintError("VNET Linux Bridge: error to initiate vnet lock\n"); - } - - return 0; -} - - -struct vnet_link * link_by_ip(struct vnet_brg_state * state, uint32_t ip) { - struct vnet_link * link = NULL; - - list_for_each_entry(link, &(state->link_list), node) { - if (link->dst_ip == ip) { - return link; - } - } - - return NULL; -} - -struct vnet_link * link_by_idx(struct vnet_brg_state * state, int idx) { - struct vnet_link * link = NULL; - - list_for_each_entry(link, &(state->link_list), node) { - if (link->link_idx == idx) { - return link; - } - } - return NULL; -} - -static int -udp_send(int sockid, uint32_t dst_ip, - uint16_t dst_port, uchar_t * pkt, - uint16_t len){ - if(dst_ip > 0 && dst_port > 0){ - return V3_SendTo_IP(sockid, dst_ip, dst_port, pkt, len); - } - - return V3_Send(sockid, pkt, len); -} - - -static int -udp_recv(int sockid, uint32_t * src_ip, - uint16_t * src_port, uchar_t *buf, - uint16_t len) { - - return V3_Recv(sockid, buf, len); -} - - - -static int -brg_send( struct v3_vm_info * vm, - struct v3_vnet_pkt * vnet_pkt, - void * private_data){ - struct vnet_brg_state * state = (struct vnet_brg_state *)private_data; - struct vnet_link * link = NULL; - - #ifdef CONFIG_DEBUG_VNET_LNX_BRIGE - { - PrintDebug("vnet_brg_send... pkt size: %d, link: %d, struct len: %d\n", - vnet_pkt->size, - vnet_pkt->dst_id, - sizeof(struct v3_vnet_pkt)); - } - #endif - - state->pkt_recv ++; - link = link_by_idx(state, vnet_pkt->dst_id); - if (link != NULL) { - if(link->type == SOCK_UDP){ - udp_send(link->socket, 0, 0, vnet_pkt->data, vnet_pkt->size); - state->pkt_sent ++; - }else { - PrintError("VNET Linux Bridge: wrong link type\n"); - return -1; - } - } else { - PrintDebug("VNET Linux Bridge: wrong dst link, idx: %d, discards the packet\n", vnet_pkt->dst_id); - state->pkt_drop ++; - } - - return 0; -} - - -static int init_serv(struct vnet_brg_state * state) { - int sock, err; - - if(state->serv_sock_type == SOCK_UDP){ - sock = V3_Create_UDP_Socket(); - if (sock < 0) { - PrintError("Could not create socket, Initiate VNET server error\n"); - return -1; - } - - err = V3_Bind_Socket(sock, state->serv_port); - if(err < 0){ - PrintError("Error to bind VNET Linux bridge receiving UDP socket\n"); - return -1; - } - state->serv_sock = sock; - } - - return 0; -} - -static int vnet_server(void * arg) { - struct v3_vnet_pkt pkt; - struct vnet_link *link; - struct vnet_brg_state * state = (struct vnet_brg_state *)arg; - uchar_t buf[ETHERNET_MTU]; - uint32_t ip = 0; - uint16_t port = 0; - int len; - - while (1) { - len = udp_recv(state->serv_sock, &ip, &port, buf, ETHERNET_MTU); - if(len < 0) { - PrintError("VNET Linux Bridge: receive error\n"); - continue; - } - - link = link_by_ip(state, ip); - if (link != NULL) { - pkt.src_id= link->link_idx; - } - else { - pkt.src_id= -1; - } - - pkt.size = len; - pkt.src_type = LINK_EDGE; - memcpy(pkt.header, buf, ETHERNET_HEADER_LEN); - pkt.data = buf; - - #ifdef CONFIG_DEBUG_VNET_LNX_BRIGE - { - PrintDebug("VNET Linux Bridge: recv pkt size: %d, pkt src_id: %d\n", - len, pkt.src_id); - v3_hexdump(buf, len, NULL, 0); - } - #endif - - v3_vnet_send_pkt(&pkt, NULL); - - state->pkt_recv ++; - } - - return 0; -} - - -static int vnet_lnxbrg_init() { - struct v3_vnet_bridge_ops brg_ops; - struct vnet_brg_state * state; - - state = (struct vnet_brg_state *)V3_Malloc(sizeof(struct vnet_brg_state)); - V3_ASSERT(state != NULL); - - vnet_lnxbrg_reset(state); - - brg_ops.input = brg_send; - - v3_vnet_add_bridge(NULL, &brg_ops, state); - - init_serv(state); - V3_CREATE_THREAD(vnet_server, state, "VNET_LNX_BRIDGE"); - - PrintDebug("VNET Linux Bridge initiated\n"); - - return 0; -} - - -device_register("LNX_VNET_BRIDGE", vnet_lnxbrg_init) diff --git a/palacios/src/devices/vnet_nic.c b/palacios/src/devices/vnet_nic.c index ff039e2..8e7d026 100644 --- a/palacios/src/devices/vnet_nic.c +++ b/palacios/src/devices/vnet_nic.c @@ -42,22 +42,24 @@ struct vnet_nic_state { /* called by frontend device, * tell the VNET can start sending pkt to it */ -static void start_rx(void *private_data){ - struct vnet_nic_state *vnetnic = (struct vnet_nic_state *)private_data; +static void start_rx(void * private_data){ + //struct vnet_nic_state *vnetnic = (struct vnet_nic_state *)private_data; - v3_vnet_enable_device(vnetnic->vnet_dev_id); + //v3_vnet_enable_device(vnetnic->vnet_dev_id); } /* called by frontend device, * tell the VNET stop sending pkt to it */ -static void stop_rx(void *private_data){ - struct vnet_nic_state *vnetnic = (struct vnet_nic_state *)private_data; +static void stop_rx(void * private_data){ + //struct vnet_nic_state *vnetnic = (struct vnet_nic_state *)private_data; - v3_vnet_disable_device(vnetnic->vnet_dev_id); + //v3_vnet_disable_device(vnetnic->vnet_dev_id); } /* called by frontend, send pkt to VNET */ -static int vnet_nic_send(uint8_t * buf, uint32_t len, void * private_data, struct vm_device *dest_dev){ +static int vnet_nic_send(uint8_t * buf, uint32_t len, + void * private_data, + struct vm_device * dest_dev){ struct vnet_nic_state *vnetnic = (struct vnet_nic_state *)private_data; struct v3_vnet_pkt pkt; @@ -79,9 +81,10 @@ static int vnet_nic_send(uint8_t * buf, uint32_t len, void * private_data, struc } -/* called by VNET, - * send pkt to frontend device */ -static int virtio_input(struct v3_vm_info *info, struct v3_vnet_pkt * pkt, void * private_data){ +/* send pkt to frontend device */ +static int virtio_input(struct v3_vm_info * info, + struct v3_vnet_pkt * pkt, + void * private_data){ struct vnet_nic_state *vnetnic = (struct vnet_nic_state *)private_data; return vnetnic->net_ops.recv(pkt->data, @@ -89,33 +92,23 @@ static int virtio_input(struct v3_vm_info *info, struct v3_vnet_pkt * pkt, void vnetnic->net_ops.frontend_data); } -/* called by VNET, - * tell frontend device to poll data from guest */ -static void virtio_poll(struct v3_vm_info *info, void * private_data){ +/* tell frontend device to poll data from guest */ +static void virtio_poll(struct v3_vm_info * info, + void * private_data){ struct vnet_nic_state *vnetnic = (struct vnet_nic_state *)private_data; vnetnic->net_ops.poll(info, vnetnic->net_ops.frontend_data); } -/* called by VNET, from different processor */ -static void virtio_poll_xcall(void *data){ - struct v3_vnet_dev_xcall_args *args = (struct v3_vnet_dev_xcall_args *)data; - struct vnet_nic_state *vnetnic = (struct vnet_nic_state *)args->private_data; - - if(args->vm == vnetnic->vm) /*only do polling on the same Virtual Machine */ - virtio_poll(args->vm, args->private_data); -} -/* called by VNET, - * tell the frontend to start sending pkt to VNET*/ +/* tell the frontend to start sending pkt to VNET*/ static void start_tx(void *private_data){ struct vnet_nic_state *vnetnic = (struct vnet_nic_state *)private_data; vnetnic->net_ops.start_tx(vnetnic->net_ops.frontend_data); } -/* called by VNET - * tell the frontend device to stop sending pkt to VNET*/ +/* tell the frontend device to stop sending pkt to VNET*/ static void stop_tx(void *private_data){ struct vnet_nic_state *vnetnic = (struct vnet_nic_state *)private_data; @@ -137,7 +130,6 @@ static struct v3_device_ops dev_ops = { static struct v3_vnet_dev_ops vnet_dev_ops = { .input = virtio_input, .poll = virtio_poll, - .poll_xcall = virtio_poll_xcall, .start_tx = start_tx, .stop_tx = stop_tx, }; diff --git a/palacios/src/palacios/vmm_vnet_core.c b/palacios/src/palacios/vmm_vnet_core.c index e263735..3726c41 100644 --- a/palacios/src/palacios/vmm_vnet_core.c +++ b/palacios/src/palacios/vmm_vnet_core.c @@ -30,46 +30,6 @@ #define PrintDebug(fmt, args...) #endif - -/* for UDP encapuslation */ -struct eth_header { - uchar_t dest[6]; - uchar_t src[6]; - uint16_t type; -}__attribute__((packed)); - -struct ip_header { - uint8_t version: 4; - uint8_t hdr_len: 4; - uchar_t tos; - uint16_t total_len; - uint16_t id; - uint8_t flags: 3; - uint16_t offset: 13; - uchar_t ttl; - uchar_t proto; - uint16_t cksum; - uint32_t src_addr; - uint32_t dst_addr; -}__attribute__((packed)); - -struct udp_header { - uint16_t src_port; - uint16_t dst_port; - uint16_t len; - uint16_t csum;//set to zero, disable the xsum -}__attribute__((packed)); - -struct udp_link_header { - struct eth_header eth_hdr; - struct ip_header ip_hdr; - struct udp_header udp_hdr; -}__attribute__((packed)); -/* end with UDP encapuslation structures */ - - - - struct eth_hdr { uint8_t dst_mac[6]; uint8_t src_mac[6]; @@ -84,7 +44,8 @@ struct vnet_dev { struct v3_vnet_dev_ops dev_ops; void * private_data; - int rx_disabled; + int active; + uint8_t mode; //vmm_drivern or guest_drivern struct list_head node; } __attribute__((packed)); @@ -94,7 +55,9 @@ struct vnet_brg_dev { struct v3_vm_info * vm; struct v3_vnet_bridge_ops brg_ops; - int disabled; + uint8_t type; + uint8_t mode; + int active; void * private_data; } __attribute__((packed)); @@ -119,15 +82,6 @@ struct route_list { } __attribute__((packed)); -#define BUF_SIZE 4096 -struct pkts_buf { - int start, end; - int num; - v3_lock_t lock; - struct v3_vnet_pkt pkts[BUF_SIZE]; -}; - - static struct { struct list_head routes; struct list_head devs; @@ -139,15 +93,11 @@ static struct { v3_lock_t lock; - uint8_t sidecores; /* 0 -vnet not running on sidecore, > 0, number of extra cores that can be used by VNET */ - uint64_t cores_map; /* bitmaps for which cores can be used by VNET for sidecore, maxium 64 */ - struct hashtable * route_cache; } vnet_state; - #ifdef CONFIG_DEBUG_VNET static inline void mac_to_string(char mac[6], char * buf) { snprintf(buf, 100, "%d:%d:%d:%d:%d:%d", @@ -442,65 +392,6 @@ static struct route_list * match_route(const struct v3_vnet_pkt * pkt) { return matches; } -static int send_to_bridge(struct v3_vnet_pkt * pkt){ - struct vnet_brg_dev *bridge = vnet_state.bridge; - - if (bridge == NULL) { - PrintError("VNET: No bridge to sent data to links\n"); - return -1; - } - - return bridge->brg_ops.input(bridge->vm, pkt, bridge->private_data); -} - - -/* enable a vnet device, notify VNET it can send pkts to it */ -int v3_vnet_enable_device(int dev_id){ - struct vnet_dev *dev = find_dev_by_id(dev_id); - unsigned long flags; - - if(!dev) - return -1; - - if(!dev->rx_disabled) - return 0; - - flags = v3_lock_irqsave(vnet_state.lock); - dev->rx_disabled = 0; - v3_unlock_irqrestore(vnet_state.lock, flags); - - /* TODO: Wake up all other guests who are trying to send pkts */ - dev = NULL; - list_for_each_entry(dev, &(vnet_state.devs), node) { - if (dev->dev_id != dev_id) - dev->dev_ops.start_tx(dev->private_data); - } - - return 0; -} - -/* Notify VNET to stop sending pkts to it */ -int v3_vnet_disable_device(int dev_id){ - struct vnet_dev *dev = find_dev_by_id(dev_id); - unsigned long flags; - - if(!dev) - return -1; - - flags = v3_lock_irqsave(vnet_state.lock); - dev->rx_disabled = 1; - v3_unlock_irqrestore(vnet_state.lock, flags); - - - /* TODO: Notify all other guests to stop send pkts */ - dev = NULL; - list_for_each_entry(dev, &(vnet_state.devs), node) { - if (dev->dev_id != dev_id) - dev->dev_ops.stop_tx(dev->private_data); - } - - return 0; -} int v3_vnet_send_pkt(struct v3_vnet_pkt * pkt, void * private_data) { struct route_list * matched_routes = NULL; @@ -545,23 +436,29 @@ int v3_vnet_send_pkt(struct v3_vnet_pkt * pkt, void * private_data) { for (i = 0; i < matched_routes->num_routes; i++) { struct vnet_route_info * route = matched_routes->routes[i]; - if (route->route_def.dst_type == LINK_EDGE) { + if (route->route_def.dst_type == LINK_EDGE) { + struct vnet_brg_dev *bridge = vnet_state.bridge; pkt->dst_type = LINK_EDGE; pkt->dst_id = route->route_def.dst_id; - if (send_to_bridge(pkt) == -1) { + if (bridge == NULL || (bridge->active == 0)) { + PrintError("VNET: No active bridge to sent data to links\n"); + continue; + } + + if(bridge->brg_ops.input(bridge->vm, pkt, bridge->private_data) == -1){ PrintDebug("VNET: Packet not sent properly to bridge\n"); continue; } } else if (route->route_def.dst_type == LINK_INTERFACE) { - if (!route->dst_dev->rx_disabled){ + if (route->dst_dev && route->dst_dev->active){ if(route->dst_dev->dev_ops.input(route->dst_dev->vm, pkt, route->dst_dev->private_data) == -1) { PrintDebug("VNET: Packet not sent properly\n"); continue; } } } else { - PrintError("VNET: Wrong Edge type\n"); + PrintError("VNET: Wrong dst type\n"); } PrintDebug("VNET: Forward one packet according to Route %d\n", i); @@ -611,37 +508,31 @@ int v3_vnet_add_dev(struct v3_vm_info *vm, uint8_t mac[6], } -/* TODO: Still need to figure out how to handle this multicore part --Lei - */ -void v3_vnet_poll(struct v3_vm_info *vm){ +void v3_vnet_poll(struct v3_vm_info * vm){ struct vnet_dev * dev = NULL; + struct vnet_brg_dev *bridge = vnet_state.bridge; - switch (vnet_state.sidecores) { - case 0: - list_for_each_entry(dev, &(vnet_state.devs), node) { - if(dev->vm == vm){ - dev->dev_ops.poll(vm, dev->private_data); - } - } - break; - case 1: - break; - case 2: - list_for_each_entry(dev, &(vnet_state.devs), node) { - int cpu_id = vm->cores[0].cpu_id + 2; /* temporary here, should use vnet_state.cores_map */ - struct v3_vnet_dev_xcall_args dev_args; /* could cause problem here -LX */ - dev_args.vm = vm; - dev_args.private_data = dev->private_data; - V3_Call_On_CPU(cpu_id, dev->dev_ops.poll_xcall, (void *)&dev_args); - } - break; - default: - break; + list_for_each_entry(dev, &(vnet_state.devs), node) { + if(dev->mode == VMM_DRIVERN && + dev->active && + dev->vm == vm){ + + dev->dev_ops.poll(vm, dev->private_data); + } } + + if (bridge != NULL && + bridge->active && + bridge->mode == VMM_DRIVERN) { + + bridge->brg_ops.poll(bridge->vm, bridge->private_data); + } + } int v3_vnet_add_bridge(struct v3_vm_info * vm, - struct v3_vnet_bridge_ops *ops, + struct v3_vnet_bridge_ops * ops, + uint8_t type, void * priv_data) { unsigned long flags; int bridge_free = 0; @@ -671,10 +562,11 @@ int v3_vnet_add_bridge(struct v3_vm_info * vm, tmp_bridge->vm = vm; tmp_bridge->brg_ops.input = ops->input; - tmp_bridge->brg_ops.xcall_input = ops->xcall_input; - tmp_bridge->brg_ops.polling_pkt = ops->polling_pkt; + tmp_bridge->brg_ops.poll = ops->poll; tmp_bridge->private_data = priv_data; - tmp_bridge->disabled = 0; + tmp_bridge->active = 1; + tmp_bridge->mode = GUEST_DRIVERN; + tmp_bridge->type = type; /* make this atomic to avoid possible race conditions */ flags = v3_lock_irqsave(vnet_state.lock); @@ -685,37 +577,6 @@ int v3_vnet_add_bridge(struct v3_vm_info * vm, } -#if 0 -int v3_vnet_disable_bridge() { - unsigned long flags; - - flags = v3_lock_irqsave(vnet_state.lock); - - if (vnet_state.bridge != NULL) { - vnet_state.bridge->disabled = 1; - } - - v3_unlock_irqrestore(vnet_state.lock, flags); - - return 0; -} - - -int v3_vnet_enable_bridge() { - unsigned long flags; - - flags = v3_lock_irqsave(vnet_state.lock); - - if (vnet_state.bridge != NULL) { - vnet_state.bridge->disabled = 0; - } - - v3_unlock_irqrestore(vnet_state.lock, flags); - - return 0; -} -#endif - int v3_init_vnet() { memset(&vnet_state, 0, sizeof(vnet_state)); @@ -739,9 +600,6 @@ int v3_init_vnet() { return -1; } - vnet_state.sidecores = 0; - vnet_state.cores_map = 0; - PrintDebug("VNET: initiated\n"); return 0;