From: Lei Xia Date: Wed, 17 Feb 2010 20:17:01 +0000 (-0600) Subject: Update on VNET-NIC device, and fix vnet & virtio net X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=commitdiff_plain;h=2774b84f1350366477eb820c7b7a2a0f56a0e074;p=palacios.git Update on VNET-NIC device, and fix vnet & virtio net --- diff --git a/Kconfig b/Kconfig index 726a7b6..1ae4408 100644 --- a/Kconfig +++ b/Kconfig @@ -108,6 +108,14 @@ config VNET help Enable the Vnet in Palacios +config DEBUG_VNET + depends on EXPERIMENTAL && VNET + bool "Enable Vnet Debug in Palacios" + default n + help + Enable the Vnet debug in Palacios + + endmenu diff --git a/palacios/include/palacios/vmm_dev_mgr.h b/palacios/include/palacios/vmm_dev_mgr.h index 7e4708f..84fd53c 100644 --- a/palacios/include/palacios/vmm_dev_mgr.h +++ b/palacios/include/palacios/vmm_dev_mgr.h @@ -159,8 +159,12 @@ struct v3_dev_blk_ops { struct v3_dev_net_ops { int (*send)(uint8_t * buf, uint32_t count, void * private_data, struct vm_device *dest_dev); - int (*receive)(uint8_t * buf, uint32_t count, void * private_data, struct vm_device *src_dev); - + int (*register_input)(void *backend_data, + int (*frontend_input)(struct v3_vm_info *info, + uchar_t * buf, + uint32_t size, + void *private_data), + void *front_data); }; struct v3_dev_console_ops { diff --git a/palacios/src/devices/Kconfig b/palacios/src/devices/Kconfig index d6c5202..43643ce 100644 --- a/palacios/src/devices/Kconfig +++ b/palacios/src/devices/Kconfig @@ -165,7 +165,7 @@ config VNET_NIC help Enable the VNET NIC backend device -config VNET_NIC_NET +config DEBUG_VNET_NIC bool "VNET NIC Device Debugging" default n depends on VNET_NIC && DEBUG_ON diff --git a/palacios/src/devices/lnx_virtio_nic.c b/palacios/src/devices/lnx_virtio_nic.c index 58e9e58..69e8293 100644 --- a/palacios/src/devices/lnx_virtio_nic.c +++ b/palacios/src/devices/lnx_virtio_nic.c @@ -66,7 +66,7 @@ struct virtio_net_config struct virtio_dev_state { struct vm_device * pci_bus; struct list_head dev_list; - struct guest_info * vm; + struct guest_info *vm; }; struct virtio_net_state { @@ -82,7 +82,6 @@ struct virtio_net_state { struct virtio_queue ctrl_vq; //index 2, ctrol info from guest ulong_t pkt_sent, pkt_recv, pkt_drop; - struct gen_queue * inpkt_q; struct v3_dev_net_ops * net_ops; @@ -91,12 +90,6 @@ struct virtio_net_state { struct list_head dev_link; }; -#define ETHERNET_PACKET_LEN 1514 -struct eth_pkt { - uint32_t size; //size of data - char data[ETHERNET_PACKET_LEN]; -}__attribute__((packed)); - static int virtio_free(struct vm_device * dev) { @@ -129,9 +122,6 @@ static int virtio_init_state(struct virtio_net_state * virtio) virtio->pkt_sent = virtio->pkt_recv = virtio->pkt_drop = 0; - virtio->inpkt_q = v3_create_queue(); - v3_init_queue(virtio->inpkt_q); - return 0; } @@ -271,28 +261,13 @@ int send_pkt_to_guest(struct virtio_net_state * virtio, uchar_t * buf, uint_t si return offset; } -static int virtio_sendto_buf(struct virtio_net_state * net_state, uchar_t * buf, uint_t size) { - struct eth_pkt *pkt; - - pkt = (struct eth_pkt *)V3_Malloc(sizeof(struct eth_pkt)); - if(pkt == NULL){ - PrintError("Virtio NIC: Memory allocate fails\n"); - return -1; - } - - pkt->size = size; - memcpy(pkt->data, buf, size); - v3_enqueue(net_state->inpkt_q, (addr_t)pkt); - - PrintDebug("Virtio NIC: __virtio_sendto_buf: transmitting packet: (size:%d)\n", (int)pkt->size); - - return pkt->size; -} - -int virtio_dev_send(uchar_t * buf, uint32_t size, void *private_data) { +int virtio_dev_send(struct v3_vm_info *info, + uchar_t * buf, + uint32_t size, + void *private_data) { struct virtio_net_state *virtio_state = (struct virtio_net_state *)private_data; - - return virtio_sendto_buf(virtio_state, buf, size); + + return send_pkt_to_guest(virtio_state, buf, size, 1, NULL); } static int get_desc_count(struct virtio_queue * q, int index) { @@ -673,6 +648,9 @@ static int connect_fn(struct v3_vm_info * info, net_state->net_ops = ops; net_state->backend_data = private_data; + //register input callback to the backend + net_state->net_ops->register_input(net_state->backend_data, virtio_dev_send, (void *)net_state); + return 0; } @@ -693,7 +671,6 @@ static int virtio_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) { INIT_LIST_HEAD(&(virtio_state->dev_list)); virtio_state->pci_bus = pci_bus; - //virtio_state->vm = vm; struct vm_device * dev = v3_allocate_device(name, &dev_ops, virtio_state); if (v3_attach_device(vm, dev) == -1) { diff --git a/palacios/src/devices/vnet_nic.c b/palacios/src/devices/vnet_nic.c index ae1238f..2b40c50 100644 --- a/palacios/src/devices/vnet_nic.c +++ b/palacios/src/devices/vnet_nic.c @@ -26,80 +26,153 @@ #include #include -struct vnet_nic_state { - char mac[6]; +#ifndef CONFIG_DEBUG_VNET_NIC +#undef PrintDebug +#define PrintDebug(fmt, args...) +#endif + +#define ETHERNET_PACKET_LEN 1514 +struct eth_pkt { + uint32_t size; //size of data + char data[ETHERNET_PACKET_LEN]; +}__attribute__((packed)); +struct vnet_nic_state { + char mac[6]; + struct guest_info *core; + struct gen_queue * inpkt_q; + + void *frontend_data; + int (*frontend_input)(struct v3_vm_info *info, + uchar_t * buf, + uint32_t size, + void *private_data); }; //used when virtio_nic get a packet from guest and send it to the backend -// send packet to all of the virtio nic devices other than the sender -static int send(uint8_t * buf, uint32_t len, void * private_data, struct vm_device *dest_dev){ +static int vnet_send(uint8_t * buf, uint32_t len, void * private_data, struct vm_device *dest_dev){ PrintDebug("Virito NIC: In vnet_send: guest net state %p\n", private_data); v3_vnet_send_rawpkt(buf, len, private_data); return 0; } -static int receive(uint8_t * buf, uint32_t count, void * private_data, struct vm_device *src_dev){ +static int register_frontend_input(void *backend_data, + int (*frontend_input)(struct v3_vm_info *info, + uchar_t * buf, + uint32_t size, + void *private_data), + void *front_data){ + struct vnet_nic_state *dev = (struct vnet_nic_state *)backend_data; + + dev->frontend_data = front_data; + dev->frontend_input = frontend_input; return 0; } static struct v3_dev_net_ops net_ops = { - .send = send, - .receive = receive, + .send = vnet_send, + .register_input = register_frontend_input, }; +static int virtio_input(struct v3_vm_info *info, uchar_t * buf, uint32_t len, void * private_data){ + struct vnet_nic_state *vnetnic = (struct vnet_nic_state *)private_data; + + PrintDebug("Vnet-nic: In input: vnet_nic state %p\n", vnetnic); + + return vnetnic->frontend_input(info, buf, len, vnetnic->frontend_data); +} #if 0 -static int input(struct v3_vm_info *info, uchar_t * buf, uint_t len, void * private_data){ - PrintDebug("Virito NIC: In virtio_input: guest net state %p\n", private_data); +static int sendto_buf(struct vnet_nic_dev_state *vnetnic_dev, uchar_t * buf, uint_t size) { + struct eth_pkt *pkt; + + pkt = (struct eth_pkt *)V3_Malloc(sizeof(struct eth_pkt)); + if(pkt == NULL){ + PrintError("Vnet NIC: Memory allocate fails\n"); + return -1; + } + + pkt->size = size; + memcpy(pkt->data, buf, size); + v3_enqueue(vnetnic_dev->inpkt_q, (addr_t)pkt); + + PrintDebug("Vnet NIC: sendto_buf: packet: (size:%d)\n", (int)pkt->size); + + return pkt->size; +} + +/* + *called in svm/vmx handler + *iteative handled the unsent packet in incoming packet queues for + *all virtio nic devices in this guest + */ +int v3_virtionic_pktprocess(struct guest_info * info) +{ + struct eth_pkt *pkt = NULL; + struct virtio_net_state *net_state; + int i; + + //PrintDebug("Virtio NIC: processing guest %p\n", info); + for (i = 0; i < net_idx; i++) { + while (1) { + net_state = temp_net_states[i]; + if(net_state->dev->vm != info) + break; + + pkt = (struct eth_pkt *)v3_dequeue(net_state->inpkt_q); + if(pkt == NULL) + break; + + if (send_pkt_to_guest(net_state, pkt->data, pkt->size, 1, NULL)) { + PrintDebug("Virtio NIC: %p In pkt_handle: send one packet! pt length %d\n", + net_state, (int)pkt->size); + } else { + PrintDebug("Virtio NIC: %p In pkt_handle: Fail to send one packet, pt length %d, discard it!\n", + net_state, (int)pkt->size); + } + + V3_Free(pkt); + } + } + + return 0; +} - return __virtio_dev_send(buf, len, private_data); + +/* + *called in svm/vmx handler + *iteative handled the unsent packet in incoming packet queues for + *all virtio nic devices in this guest + */ +int v3_vnetnic_pktprocess(struct guest_info * info) +{ + + return 0; } +#endif //register a virtio device to the vnet as backend -void register_to_vnet(struct vm_device *dev, +int register_to_vnet(struct v3_vm_info *info, + struct vnet_nic_state *vnet_nic, char *dev_name, uchar_t mac[6]){ - struct virtio_net_state * net_state; - struct virtio_dev_state *virtio_state = (struct virtio_dev_state *)dev->private_data; - uchar_t tapmac[6] = {0x00,0x02,0x55,0x67,0x42,0x39}; //for Intel-VT test HW - //uchar_t tapmac[6] = {0x6e,0xa8,0x75,0xf4,0x82,0x95}; - uchar_t dstmac[6] = {0xff,0xff,0xff,0xff,0xff,0xff}; + uchar_t brdmac[6] = {0xff,0xff,0xff,0xff,0xff,0xff}; uchar_t zeromac[6] = {0,0,0,0,0,0}; + struct v3_vnet_route route; - - net_state = (struct virtio_net_state *)V3_Malloc(sizeof(struct virtio_net_state)); - memset(net_state, 0, sizeof(struct virtio_net_state)); - net_state->net_ops = (struct v3_dev_net_ops *)V3_Malloc(sizeof(struct v3_dev_net_ops)); - net_state->net_ops->send = &vnet_send; - net_state->net_ops->receive = &vnet_receive; - net_state->dev = dev; - - register_dev(virtio_state, net_state); - - PrintDebug("Virtio NIC register Device %s: queue size: %d, %d\n", dev->name, - net_state->rx_vq.queue_size, net_state->tx_vq.queue_size); - PrintDebug("Virtio NIC: connect virtio device %s, state %p, to vnet\n", dev->name, net_state); + PrintDebug("Vnet-nic: register Vnet-nic device %s, state %p to VNET\n", dev_name, vnet_nic); - int idx = vnet_register_device(dev, dev_name, mac, &virtio_input, net_state); - //vnet_add_route_entry(zeromac, dstmac, MAC_ANY, MAC_NONE, idx, LINK_INTERFACE, -1, LINK_INTERFACE); - if (!strcmp(dev_name, "net_virtiodom0")){ - vnet_add_route_entry(zeromac, tapmac, MAC_ANY, MAC_NONE, idx, LINK_INTERFACE, -1, LINK_INTERFACE); - vnet_add_route_entry(zeromac, dstmac, MAC_ANY, MAC_NONE, idx, LINK_INTERFACE, -1, LINK_INTERFACE); - } - if (!strcmp(dev_name, "net_virtio")) - vnet_add_route_entry(tapmac, zeromac, MAC_NONE, MAC_ANY, idx, LINK_INTERFACE, -1, LINK_INTERFACE); + int idx = v3_vnet_add_node(info, dev_name, mac, virtio_input, (void *)vnet_nic); + if (idx < 0) return -1; - v3_vnet_add_node(dev_name, mac, input, priv_data); - struct v3_vnet_route route; - //add default route - memset(&route, 0, sizeof(struct v3_vnet_route)); + //add default routes for each link edge device + memcpy(&route.src_mac, zeromac, 6); memcpy(&route.dest_mac, mac, 6); route.src_mac_qual = MAC_ANY; route.dest_mac_qual = MAC_NONE; @@ -109,33 +182,19 @@ void register_to_vnet(struct vm_device *dev, route.src_type = LINK_ANY; v3_vnet_add_route(&route); - char mac - memset(&route, 0, sizeof(struct v3_vnet_route)); - memcpy(&route.dest_mac, mac, 6); - route.src_mac_qual = MAC_ANY; + memcpy(&route.dest_mac, brdmac, 6); + memcpy(&route.src_mac, mac, 6); + route.src_mac_qual = MAC_NOT; route.dest_mac_qual = MAC_NONE; route.link_idx = idx; route.link_type = LINK_EDGE; route.src_link_idx = -1; route.src_type = LINK_ANY; v3_vnet_add_route(&route); - -} - -/* - *called in svm/vmx handler - *iteative handled the unsent packet in incoming packet queues for - *all virtio nic devices in this guest - */ -int v3_vnetnic_pktprocess(struct guest_info * info) -{ - return 0; } -#endif - static int vnet_nic_free(struct vm_device * dev) { return 0; } @@ -156,9 +215,6 @@ static int vnet_nic_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) { vnetnic = (struct vnet_nic_state *)V3_Malloc(sizeof(struct vnet_nic_state)); memset(vnetnic, 0, sizeof(struct vnet_nic_state)); - - PrintDebug("Registering vnet_nic device at\n"); - struct vm_device * dev = v3_allocate_device(name, &dev_ops, vnetnic); if (v3_attach_device(vm, dev) == -1) { @@ -172,7 +228,13 @@ static int vnet_nic_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) { name, v3_cfg_val(frontend_cfg, "tag")); return -1; } - + + vnetnic->inpkt_q = v3_create_queue(); + + if(register_to_vnet(vm, vnetnic, name, vnetnic->mac) == -1) + return -1; + + PrintDebug("Vnet-nic device %s initialized\n", name); return 0; } diff --git a/palacios/src/palacios/vmm_vnet.c b/palacios/src/palacios/vmm_vnet.c index e7a1a8d..ecaa963 100644 --- a/palacios/src/palacios/vmm_vnet.c +++ b/palacios/src/palacios/vmm_vnet.c @@ -388,38 +388,6 @@ static void dump_routes(struct routing_entry **route_tables) { PrintDebug("\nVnet: route table dump end =====\n"); } -static void dump_dom0_routes(struct routing_entry routes[], int size) { - int i; - - PrintDebug("\nVnet: route table from dom0 guest =====\n"); - - for(i = 0; i dest_ip, - link->dest_port, - link->pro_type); - PrintDebug("vnet_header:\n"); - v3_hexdump(&link->vnet_header, sizeof(struct udp_link_header), NULL, 0); - } - - PrintDebug("\nVnet: link table dom0 guest end =====\n"); -} - #endif static int __add_link_entry(struct link_entry * link) {