From: Lei Xia Date: Mon, 15 Mar 2010 16:10:28 +0000 (-0500) Subject: Minimize the copies for vnet and Virtio bridge X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=commitdiff_plain;h=58a5fd180f52b2d9e15c3613324c17123672ee19;p=palacios.git Minimize the copies for vnet and Virtio bridge --- diff --git a/palacios/include/palacios/vmm_vnet.h b/palacios/include/palacios/vmm_vnet.h index 52fc932..7298918 100644 --- a/palacios/include/palacios/vmm_vnet.h +++ b/palacios/include/palacios/vmm_vnet.h @@ -66,7 +66,8 @@ struct v3_vnet_pkt { struct { uint8_t src_type; uint32_t src_id; - uint8_t data[ETHERNET_PACKET_LEN]; + uint8_t header[ETHERNET_HEADER_LEN]; + uint8_t *data; } __attribute__((packed)); } __attribute__((packed)); } __attribute__((packed)); diff --git a/palacios/src/devices/lnx_virtio_nic.c b/palacios/src/devices/lnx_virtio_nic.c index c626708..7bcd9bb 100644 --- a/palacios/src/devices/lnx_virtio_nic.c +++ b/palacios/src/devices/lnx_virtio_nic.c @@ -478,7 +478,7 @@ static int virtio_rx(uint8_t * buf, uint32_t size, void * private_data) { uint32_t data_len = size; uint32_t offset = 0; unsigned long flags; - int ret_val; + int ret_val = -1; int raw = 1; flags = v3_lock_irqsave(virtio->lock); @@ -495,7 +495,6 @@ static int virtio_rx(uint8_t * buf, uint32_t size, void * private_data) { if (q->ring_avail_addr == 0) { PrintError("Queue is not set\n"); - ret_val = -1; goto exit; } diff --git a/palacios/src/devices/lnx_virtio_vnet.c b/palacios/src/devices/lnx_virtio_vnet.c index 4de1ab8..bfbc56c 100644 --- a/palacios/src/devices/lnx_virtio_vnet.c +++ b/palacios/src/devices/lnx_virtio_vnet.c @@ -26,7 +26,7 @@ #include -#ifndef CONFIG_LINUX_VIRTIO_VNET_DEBUG +#ifndef CONFIG_DEBUG_LINUX_VIRTIO_VNET #undef PrintDebug #define PrintDebug(fmt, args...) #endif @@ -78,8 +78,9 @@ struct vnet_ctrl_hdr { struct vnet_virtio_pkt { uint32_t link_id; uint32_t pkt_size; - uint8_t pkt[1500]; -}; + uint8_t pkt[ETHERNET_PACKET_LEN]; +}__attribute__((packed)); + static int virtio_reset(struct virtio_vnet_state * vnet_state) { @@ -222,8 +223,6 @@ static int vnet_pkt_input_cb(struct v3_vm_info * vm, struct v3_vnet_pkt * pkt, flags = v3_lock_irqsave(vnet_state->lock); - PrintDebug("VNET Bridge: RX: pkt sent to guest size: %d\n, pkt_header_len: %d\n", data_len, pkt_head_len); - if (q->ring_avail_addr == 0) { PrintError("Queue is not set\n"); goto exit; @@ -244,11 +243,12 @@ static int vnet_pkt_input_cb(struct v3_vm_info * vm, struct v3_vnet_pkt * pkt, return -1; } + PrintDebug("VNET Bridge: RX: pkt sent to guest pkt size: %d, dst link: %d\n", pkt->size, pkt->dst_id); + // Fill in dst packet buffer virtio_pkt->link_id = pkt->dst_id; virtio_pkt->pkt_size = pkt->size; memcpy(virtio_pkt->pkt, pkt->data, pkt->size); - q->used->ring[q->used->index % q->queue_size].id = q->avail->ring[q->cur_avail_idx % q->queue_size]; q->used->ring[q->used->index % q->queue_size].length = sizeof(struct vnet_virtio_pkt); // This should be the total length of data sent to guest (header+pkt_data) @@ -256,7 +256,7 @@ static int vnet_pkt_input_cb(struct v3_vm_info * vm, struct v3_vnet_pkt * pkt, q->used->index++; q->cur_avail_idx++; } else { - PrintError("Packet buffer overflow in the guest\n"); + PrintError("Packet buffer overflow in the guest: cur_avai_idx %d, idx: %d\n", q->cur_avail_idx, q->avail->index); } if (!(q->avail->flags & VIRTIO_NO_IRQ_FLAG)) { @@ -265,7 +265,6 @@ static int vnet_pkt_input_cb(struct v3_vm_info * vm, struct v3_vnet_pkt * pkt, PrintDebug("Raising IRQ %d\n", vnet_state->pci_dev->config_header.intr_line); } - ret_val = 0; exit: @@ -278,8 +277,7 @@ exit: static int handle_pkt_kick(struct guest_info *core, struct virtio_vnet_state * vnet_state) { struct virtio_queue * q = &(vnet_state->queue[XMIT_QUEUE]); - - PrintDebug("VNET Bridge Device: Handle TX\n"); + struct v3_vnet_pkt pkt; while (q->cur_avail_idx != q->avail->index) { uint16_t desc_idx = q->avail->ring[q->cur_avail_idx % q->queue_size]; @@ -288,21 +286,33 @@ static int handle_pkt_kick(struct guest_info *core, struct virtio_vnet_state * v pkt_desc = &(q->desc[desc_idx]); - PrintDebug("VNET Bridge: Handle TX buf_len: %d\n", pkt_desc->length); + PrintDebug("VNET Bridge: Handle TX desc buf_len: %d\n", pkt_desc->length); + + //PrintDebug("q: %p, %p, %p, %d\n", q, vnet_state->queue, &vnet_state->queue[XMIT_QUEUE], XMIT_QUEUE); + //PrintDebug("q->used: %p\n", q->used); + //PrintDebug("q->used->ring %p\n", q->used->ring); if (guest_pa_to_host_va(core, pkt_desc->addr_gpa, (addr_t *)&(virtio_pkt)) == -1) { PrintError("Could not translate buffer address\n"); return -1; } - //TODO: SETUP VNET PACKET data structure + PrintDebug("VNET Bridge: TX: pkt size: %d, dst link: %d\n", virtio_pkt->pkt_size, virtio_pkt->link_id); - /* - if (v3_vnet_send_pkt(pkt, (void *)core) == -1) { - PrintError("Error sending packet to vnet\n"); - return -1; - } - */ + pkt.size = virtio_pkt->pkt_size; + pkt.src_id = virtio_pkt->link_id; + pkt.src_type = LINK_EDGE; + memcpy(pkt.header, virtio_pkt->pkt, ETHERNET_HEADER_LEN); + pkt.data = virtio_pkt->pkt; + + v3_vnet_send_pkt(&pkt, NULL); + + q = (struct virtio_queue *)((addr_t)vnet_state->queue + XMIT_QUEUE*sizeof(struct virtio_queue)); + + PrintDebug("After q: %p, , %p, %p, %d\n", q, vnet_state->queue, &(vnet_state->queue[XMIT_QUEUE]), XMIT_QUEUE); + //PrintDebug("After q->used: %p\n", q->used); + //PrintDebug("After q->used->ring %p\n", q->used->ring); + q->used->ring[q->used->index % q->queue_size].id = q->avail->ring[q->cur_avail_idx % q->queue_size]; q->used->ring[q->used->index % q->queue_size].length = pkt_desc->length; // What do we set this to???? q->used->index++; diff --git a/palacios/src/devices/vnet_nic.c b/palacios/src/devices/vnet_nic.c index 86f5ba7..7290038 100644 --- a/palacios/src/devices/vnet_nic.c +++ b/palacios/src/devices/vnet_nic.c @@ -49,7 +49,8 @@ static int vnet_send(uint8_t * buf, uint32_t len, void * private_data, struct vm pkt.size = len; pkt.src_type = LINK_INTERFACE; pkt.src_id = vnetnic->vnet_dev_id; - memcpy(pkt.data, buf, pkt.size); + memcpy(pkt.header, buf, ETHERNET_HEADER_LEN); + pkt.data = buf; #ifdef CONFIG_DEBUG_VNET_NIC { diff --git a/palacios/src/palacios/vmm_vnet.c b/palacios/src/palacios/vmm_vnet.c index bdc4719..38a9087 100644 --- a/palacios/src/palacios/vmm_vnet.c +++ b/palacios/src/palacios/vmm_vnet.c @@ -169,7 +169,7 @@ static inline int hash_eq(addr_t key1, addr_t key2) { } -static int add_route_to_cache(struct v3_vnet_pkt * pkt, struct route_list * routes) { +static int add_route_to_cache(const struct v3_vnet_pkt * pkt, struct route_list * routes) { memcpy(routes->hash_buf, pkt->hash_buf, VNET_HASH_SIZE); if (v3_htable_insert(vnet_state.route_cache, (addr_t)routes->hash_buf, (addr_t)routes) == 0) { @@ -188,7 +188,7 @@ static int clear_hash_cache() { return 0; } -static int look_into_cache(struct v3_vnet_pkt * pkt, struct route_list ** routes) { +static int look_into_cache(const struct v3_vnet_pkt * pkt, struct route_list ** routes) { *routes = (struct route_list *)v3_htable_search(vnet_state.route_cache, (addr_t)(pkt->hash_buf)); @@ -279,7 +279,7 @@ int v3_vnet_add_route(struct v3_vnet_route route) { // At the end allocate a route_list // This list will be inserted into the cache so we don't need to free it -static struct route_list * match_route(struct v3_vnet_pkt * pkt) { +static struct route_list * match_route(const struct v3_vnet_pkt * pkt) { struct vnet_route_info * route = NULL; struct route_list * matches = NULL; int num_matches = 0; @@ -411,7 +411,7 @@ int v3_vnet_send_pkt(struct v3_vnet_pkt * pkt, void * private_data) { #ifdef CONFIG_DEBUG_VNET { - struct eth_hdr * hdr = (struct eth_hdr *)(pkt->data); + struct eth_hdr * hdr = (struct eth_hdr *)(pkt->header); char dest_str[30]; char src_str[30]; @@ -426,14 +426,14 @@ int v3_vnet_send_pkt(struct v3_vnet_pkt * pkt, void * private_data) { look_into_cache(pkt, &matched_routes); if (matched_routes == NULL) { - PrintDebug("Vnet: can not find route in cache, looking into routing table\n"); + PrintDebug("Vnet: send pkt Looking into routing table\n"); matched_routes = match_route(pkt); if (matched_routes) { add_route_to_cache(pkt, matched_routes); } else { - PrintDebug("Could not find route for packet...\n"); + PrintDebug("Could not find route for packet... discards packet\n"); v3_unlock_irqrestore(vnet_state.lock, flags); return -1; } @@ -442,7 +442,7 @@ int v3_vnet_send_pkt(struct v3_vnet_pkt * pkt, void * private_data) { v3_unlock_irqrestore(vnet_state.lock, flags); - PrintDebug("Vnet: HandleOnePacket: route matches %d\n", matched_routes->num_routes); + PrintDebug("Vnet: send pkt route matches %d\n", matched_routes->num_routes); for (i = 0; i < matched_routes->num_routes; i++) { struct vnet_route_info * route = matched_routes->routes[i];