From: Lei Xia Date: Mon, 1 Mar 2010 05:37:41 +0000 (-0600) Subject: Fix to vnet/virtio networking X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=commitdiff_plain;h=17f8752ad440dba7d414d0812e3680066dcb8c9e;p=palacios.git Fix to vnet/virtio networking --- diff --git a/palacios/include/palacios/vmm_vnet.h b/palacios/include/palacios/vmm_vnet.h index 49951ad..452f325 100644 --- a/palacios/include/palacios/vmm_vnet.h +++ b/palacios/include/palacios/vmm_vnet.h @@ -72,7 +72,21 @@ struct v3_vnet_pkt { } __attribute__((packed)); -int v3_vnet_send_pkt(struct v3_vnet_pkt * pkt); +#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 vnet_handle_time; + + uint64_t virtio_handle_start; +}; +#endif + + +int v3_vnet_send_pkt(struct v3_vnet_pkt * pkt, void *private_data); int v3_vnet_add_route(struct v3_vnet_route route); diff --git a/palacios/src/devices/lnx_virtio_nic.c b/palacios/src/devices/lnx_virtio_nic.c index 8792174..a2abb6e 100644 --- a/palacios/src/devices/lnx_virtio_nic.c +++ b/palacios/src/devices/lnx_virtio_nic.c @@ -27,6 +27,7 @@ #include #include #include +#include #include @@ -143,7 +144,7 @@ static int pkt_tx(struct guest_info *core, struct virtio_net_state * virtio, str return -1; } - if (virtio->net_ops->send(buf, len, (void *)virtio, NULL) == -1) { + if (virtio->net_ops->send(buf, len, (void *)core, NULL) == -1) { return -1; } @@ -264,6 +265,20 @@ static int handle_pkt_tx(struct guest_info *core, struct virtio_net_state * virt PrintError("Virtio NIC: %p, pkt_sent: %ld\n", virtio_state, virtio_state->pkt_sent); #endif +#ifdef CONFIG_VNET_PROFILE + uint64_t time; + rdtscll(time); + core->vnet_times.total_handle_time = time - core->vnet_times.virtio_handle_start; + + PrintError("Vnet_profiling: total_handle_time: %ld vnet_time: %ld copy_from_guest: %ld copy_to_guest: %ld malloc_free: %ld, route_lookup: %ld\n", + (long)core->vnet_times.total_handle_time, + (long)core->vnet_times.vnet_handle_time, + (long)core->vnet_times.time_copy_from_guest, + (long)core->vnet_times.time_copy_to_guest, + (long)core->vnet_times.time_mallocfree, + (long)core->vnet_times.time_route_lookup); +#endif + return 0; } @@ -281,31 +296,23 @@ static int virtio_setup_queue(struct guest_info *core, (sizeof(struct vring_avail)) + (queue->queue_size * sizeof(uint16_t))); - PrintDebug("Virtio NIC: In setup queue: queue %p\n", (void *)queue); - // round up to next page boundary. queue->ring_used_addr = (queue->ring_used_addr + 0xfff) & ~0xfff; if (guest_pa_to_host_va(core, queue->ring_desc_addr, (addr_t *)&(queue->desc)) == -1) { PrintError("Could not translate ring descriptor address\n"); return -1; } - - PrintDebug("Virtio NIC: In setup queue111: queue %p\n", (void *)queue); if (guest_pa_to_host_va(core, queue->ring_avail_addr, (addr_t *)&(queue->avail)) == -1) { PrintError("Could not translate ring available address\n"); return -1; } - PrintDebug("Virtio NIC: In setup queue222: queue %p\n", (void *)queue); - if (guest_pa_to_host_va(core, queue->ring_used_addr, (addr_t *)&(queue->used)) == -1) { PrintError("Could not translate ring used address\n"); return -1; } - PrintDebug("Virtio NIC: In setup queue333: queue %p\n", (void *)queue); - PrintDebug("RingDesc_addr=%p, Avail_addr=%p, Used_addr=%p\n", (void *)(queue->ring_desc_addr), (void *)(queue->ring_avail_addr), @@ -322,6 +329,12 @@ static int virtio_io_write(struct guest_info *core, uint16_t port, void * src, u struct virtio_net_state * virtio = (struct virtio_net_state *)private_data; int port_idx = port % virtio->io_range_size; +#ifdef CONFIG_VNET_PROFILE + uint64_t time; + rdtscll(time); + core->vnet_times.virtio_handle_start = time; +#endif + PrintDebug("VIRTIO NIC %p Write for port %d (index=%d) len=%d, value=%x\n", private_data, port, port_idx, length, *(uint32_t *)src); @@ -504,15 +517,19 @@ static int virtio_rx(uint8_t * buf, uint32_t size, void * private_data) { uint32_t offset = 0; unsigned long flags; int ret_val; + int raw = 1; flags = v3_lock_irqsave(virtio->lock); PrintDebug("VIRTIO NIC: receiving packet to virtio nic %p, size:%d\n", virtio, size); virtio->pkt_recv ++; - data_len -= hdr_len; - build_receive_header(&hdr, buf, 1); + if (!raw){ + data_len -= hdr_len; + } + + build_receive_header(&hdr, buf, raw); if (q->ring_avail_addr == 0) { PrintError("Queue is not set\n"); diff --git a/palacios/src/devices/vnet_nic.c b/palacios/src/devices/vnet_nic.c index abdd227..8b1280d 100644 --- a/palacios/src/devices/vnet_nic.c +++ b/palacios/src/devices/vnet_nic.c @@ -42,34 +42,65 @@ struct vnet_nic_state { //used when virtio_nic get a packet from guest and send it to the backend static int vnet_send(uint8_t * buf, uint32_t len, void * private_data, struct vm_device *dest_dev){ struct v3_vnet_pkt * pkt = NULL; + struct guest_info *core = (struct guest_info *)private_data; PrintDebug("Virtio VNET-NIC: send pkt size: %d\n", len); #ifdef CONFIG_DEBUG_VNET_NIC v3_hexdump(buf, len, NULL, 0); #endif +#ifdef CONFIG_VNET_PROFILE + uint64_t start, end; + rdtscll(start); +#endif + pkt = (struct v3_vnet_pkt *)V3_Malloc(sizeof(struct v3_vnet_pkt)); if(pkt == NULL){ PrintError("Malloc() fails"); return -1; } + +#ifdef CONFIG_VNET_PROFILE + { + rdtscll(end); + core->vnet_times.time_mallocfree = end - start; + } +#endif + pkt->size = len; memcpy(pkt->data, buf, pkt->size); - v3_vnet_send_pkt(pkt); +#ifdef CONFIG_VNET_PROFILE + { + rdtscll(start); + core->vnet_times.time_copy_from_guest = start - end; + } +#endif + + v3_vnet_send_pkt(pkt, (void *)core); + +#ifdef CONFIG_VNET_PROFILE + { + rdtscll(end); + core->vnet_times.vnet_handle_time = end - start; + } +#endif V3_Free(pkt); + +#ifdef CONFIG_VNET_PROFILE + { + rdtscll(start); + core->vnet_times.time_mallocfree += start - end; + } +#endif + return 0; } -// We need to make this dynamically allocated -//static struct v3_dev_net_ops net_ops = { -// .send = vnet_send, -//}; - 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; @@ -78,87 +109,14 @@ static int virtio_input(struct v3_vm_info *info, struct v3_vnet_pkt * pkt, void return vnetnic->net_ops.recv(pkt->data, pkt->size, vnetnic->net_ops.frontend_data); } -#if 0 -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; -} - - -/* - *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 -int register_to_vnet(struct v3_vm_info * vm, +static int register_to_vnet(struct v3_vm_info * vm, struct vnet_nic_state *vnet_nic, char *dev_name, uchar_t mac[6]) { PrintDebug("Vnet-nic: register Vnet-nic device %s, state %p to VNET\n", dev_name, vnet_nic); - v3_vnet_add_dev(vm, mac, virtio_input, (void *)vnet_nic); - - return 0; + return v3_vnet_add_dev(vm, mac, virtio_input, (void *)vnet_nic); } static int vnet_nic_free(struct vm_device * dev) { @@ -172,11 +130,32 @@ static struct v3_device_ops dev_ops = { .stop = NULL, }; + +static int str2mac(char *macstr, char mac[6]){ + char hex[2], *s = macstr; + int i = 0; + + while(s){ + memcpy(hex, s, 2); + mac[i++] = (char)atox(hex); + if (i == 6) return 0; + s=strchr(s, ':'); + if(s) s++; + } + + return -1; +} + static int vnet_nic_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) { struct vnet_nic_state * vnetnic = NULL; char * name = v3_cfg_val(cfg, "name"); + char * macstr; + char mac[6]; + int vnet_dev_id; v3_cfg_tree_t * frontend_cfg = v3_cfg_subtree(cfg, "frontend"); + macstr = v3_cfg_val(frontend_cfg, "mac"); + str2mac(macstr, mac); vnetnic = (struct vnet_nic_state *)V3_Malloc(sizeof(struct vnet_nic_state)); memset(vnetnic, 0, sizeof(struct vnet_nic_state)); @@ -189,6 +168,8 @@ static int vnet_nic_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) { } vnetnic->net_ops.send = vnet_send; + memcpy(vnetnic->mac, mac, 6); + if (v3_dev_connect_net(vm, v3_cfg_val(frontend_cfg, "tag"), &(vnetnic->net_ops), frontend_cfg, vnetnic) == -1) { PrintError("Could not connect %s to frontend %s\n", @@ -196,11 +177,57 @@ static int vnet_nic_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) { return -1; } - if (register_to_vnet(vm, vnetnic, name, vnetnic->mac) == -1) { + PrintDebug("Vnet-nic: Connect %s to frontend %s\n", + name, v3_cfg_val(frontend_cfg, "tag")); + + if ((vnet_dev_id = register_to_vnet(vm, vnetnic, name, vnetnic->mac)) == -1) { return -1; } - PrintDebug("Vnet-nic device %s initialized\n", name); + PrintDebug("Vnet-nic device %s (mac: %s, %ld) initialized\n", name, macstr, *((ulong_t *)vnetnic->mac)); + + +//for temporary hack +#if 1 + { + //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 zeromac[6] = {0,0,0,0,0,0}; + + struct v3_vnet_route route; + route.dst_id = vnet_dev_id; + route.dst_type = LINK_INTERFACE; + route.src_id = -1; + route.src_type = LINK_ANY; + + if(!strcmp(name, "vnet_nicdom0")){ + memcpy(route.dst_mac, tapmac, 6); + route.dst_mac_qual = MAC_NONE; + memcpy(route.src_mac, zeromac, 6); + route.src_mac_qual = MAC_ANY; + + v3_vnet_add_route(route); + + memcpy(route.dst_mac, dstmac, 6); + route.dst_mac_qual = MAC_NONE; + memcpy(route.src_mac, tapmac, 6); + route.src_mac_qual = MAC_NOT; + + v3_vnet_add_route(route); + } + + if (!strcmp(name, "vnet_nic0")){ + memcpy(route.dst_mac, zeromac, 6); + route.dst_mac_qual = MAC_ANY; + memcpy(route.src_mac, tapmac, 6); + route.src_mac_qual = MAC_NONE; + + v3_vnet_add_route(route); + } + } + +#endif return 0; } diff --git a/palacios/src/palacios/vmm_vnet.c b/palacios/src/palacios/vmm_vnet.c index d2602c5..f87ad58 100644 --- a/palacios/src/palacios/vmm_vnet.c +++ b/palacios/src/palacios/vmm_vnet.c @@ -99,11 +99,47 @@ static struct { #ifdef CONFIG_DEBUG_VNET static inline void mac_to_string(char mac[6], char * buf) { - snprintf(buf, 20, "%02x:%02x:%02x:%02x:%02x:%02x", + snprintf(buf, 50, "%x:%x:%x:%x:%x:%x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); } +static void print_route(struct vnet_route_info *route){ + char str[50]; + + mac_to_string(route->route_def.src_mac, str); + PrintDebug("Src Mac (%s), src_qual (%d)\n", + str, route->route_def.src_mac_qual); + mac_to_string(route->route_def.dst_mac, str); + PrintDebug("Dst Mac (%s), dst_qual (%d)\n", + str, route->route_def.dst_mac_qual); + PrintDebug("Src dev id (%d), src type (%d)", + route->route_def.src_id, + route->route_def.src_type); + PrintDebug("Dst dev id (%d), dst type (%d)", + route->route_def.dst_id, + route->route_def.dst_type); + PrintDebug("dst_dev (%p), dst_dev_id (%d), dst_dev_input (%p), dst_dev_data (%p)\n", + route->dst_dev, + route->dst_dev->dev_id, + route->dst_dev->input, + route->dst_dev->private_data); + +} + +static void dump_routes(){ + struct vnet_route_info *route; + + int i = 0; + PrintDebug("\n========Dump routes starts ============\n"); + list_for_each_entry(route, &(vnet_state.routes), node) { + PrintDebug("\nroute %d:\n", ++i); + + print_route(route); + } + PrintDebug("\n========Dump routes end ============\n"); +} + #endif @@ -149,7 +185,7 @@ static int look_into_cache(struct v3_vnet_pkt * pkt, struct route_list ** routes } -struct vnet_dev * find_dev_by_id(int idx) { +static struct vnet_dev * find_dev_by_id(int idx) { struct vnet_dev * dev = NULL; list_for_each_entry(dev, &(vnet_state.devs), node) { @@ -162,17 +198,27 @@ struct vnet_dev * find_dev_by_id(int idx) { return NULL; } -static struct vnet_dev * find_dev_by_mac(char * name) { +static struct vnet_dev * find_dev_by_mac(char mac[6]) { struct vnet_dev * dev = NULL; list_for_each_entry(dev, &(vnet_state.devs), node) { - if (!memcmp(dev->mac_addr, name, 6)) + if (!memcmp(dev->mac_addr, mac, 6)) return dev; } return NULL; } +int get_device_id_by_mac(char mac[6]){ + + struct vnet_dev *dev = find_dev_by_mac(mac); + + if (dev == NULL) + return -1; + + return dev->dev_id; +} + int v3_vnet_add_route(struct v3_vnet_route route) { struct vnet_route_info * new_route = NULL; @@ -181,13 +227,22 @@ int v3_vnet_add_route(struct v3_vnet_route route) { new_route = (struct vnet_route_info *)V3_Malloc(sizeof(struct vnet_route_info)); memset(new_route, 0, sizeof(struct vnet_route_info)); - PrintDebug("Vnet: vnet_add_route_entry\n"); + PrintDebug("Vnet: vnet_add_route_entry: dst_id: %d, dst_type: %d\n", + route.dst_id, route.dst_type); - new_route->route_def = route; + memcpy(new_route->route_def.src_mac, route.src_mac, 6); + memcpy(new_route->route_def.dst_mac, route.dst_mac, 6); + new_route->route_def.src_mac_qual = route.src_mac_qual; + new_route->route_def.dst_mac_qual = route.dst_mac_qual; + new_route->route_def.dst_id = route.dst_id; + new_route->route_def.dst_type = route.dst_type; + new_route->route_def.src_id = route.src_id; + new_route->route_def.src_type = route.src_type; - /* TODO: Find devices */ if (new_route->route_def.dst_type == LINK_INTERFACE) { new_route->dst_dev = find_dev_by_id(new_route->route_def.dst_id); + PrintDebug("Vnet: Add route, get device: dev_id %d, input : %p, private_data %p\n", + new_route->dst_dev->dev_id, new_route->dst_dev->input, new_route->dst_dev->private_data); } if (new_route->route_def.src_type == LINK_INTERFACE) { @@ -200,6 +255,10 @@ int v3_vnet_add_route(struct v3_vnet_route route) { clear_hash_cache(); +#ifdef CONFIG_DEBUG_VNET + dump_routes(); +#endif + return 0; } @@ -219,8 +278,8 @@ static struct route_list * match_route(struct v3_vnet_pkt * pkt) { #ifdef CONFIG_DEBUG_VNET { - char dst_str[18]; - char src_str[18]; + char dst_str[50]; + char src_str[50]; mac_to_string(hdr->src_mac, src_str); mac_to_string(hdr->dst_mac, dst_str); @@ -304,7 +363,7 @@ static struct route_list * match_route(struct v3_vnet_pkt * pkt) { } // Default route - if ( (memcmp(route_def->src_mac, hdr->src_mac, 6) == 0) & + if ( (memcmp(route_def->src_mac, hdr->src_mac, 6) == 0) && (route_def->dst_mac_qual == MAC_NONE)) { UPDATE_MATCHES(4); } @@ -323,7 +382,7 @@ static struct route_list * match_route(struct v3_vnet_pkt * pkt) { { int i = 0; - list_for_each_entry(route, &match_list, node) { + list_for_each_entry(route, &match_list, match_node) { matches->routes[i++] = route; } } @@ -331,7 +390,7 @@ static struct route_list * match_route(struct v3_vnet_pkt * pkt) { return matches; } -static int handle_one_pkt(struct v3_vnet_pkt * pkt) { +static int handle_one_pkt(struct v3_vnet_pkt * pkt, void *private_data) { struct route_list * matched_routes = NULL; unsigned long flags; int i; @@ -340,8 +399,8 @@ static int handle_one_pkt(struct v3_vnet_pkt * pkt) { #ifdef CONFIG_DEBUG_VNET { struct eth_hdr * hdr = (struct eth_hdr *)(pkt->data); - char dest_str[18]; - char src_str[18]; + char dest_str[30]; + char src_str[30]; mac_to_string(hdr->src_mac, src_str); mac_to_string(hdr->dst_mac, dest_str); @@ -349,28 +408,41 @@ static int handle_one_pkt(struct v3_vnet_pkt * pkt) { } #endif +#ifdef CONFIG_VNET_PROFILE + struct guest_info *core = (struct guest_info *)private_data; + uint64_t start, end; + rdtscll(start); +#endif + flags = v3_lock_irqsave(vnet_state.lock); look_into_cache(pkt, &matched_routes); if (matched_routes == NULL) { - matched_routes = match_route(pkt); + matched_routes = match_route(pkt); - if (matched_routes) { + if (matched_routes) { add_route_to_cache(pkt, matched_routes); } else { - PrintError("Could not find route for packet...\n"); + PrintDebug("Could not find route for packet...\n"); v3_unlock_irqrestore(vnet_state.lock, flags); return -1; } } v3_unlock_irqrestore(vnet_state.lock, flags); - - - for (i = 0; i < matched_routes->num_routes; i++) { - struct vnet_route_info * route = matched_routes->routes[i]; +#ifdef CONFIG_VNET_PROFILE + { + rdtscll(end); + core->vnet_times.time_route_lookup = end - start; + } +#endif + + PrintDebug("Vnet: HandleOnePacket: %d\n", matched_routes->num_routes); + 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) { } else if (route->route_def.dst_type == LINK_INTERFACE) { @@ -383,17 +455,23 @@ static int handle_one_pkt(struct v3_vnet_pkt * pkt) { continue; } - PrintDebug("Vnet: HandleDataOverLink: Forward packet according to Route\n"); + PrintDebug("Vnet: HandleOnePacket: Forward packet according to Route\n"); } + +#ifdef CONFIG_VNET_PROFILE + { + rdtscll(start); + core->vnet_times.time_copy_to_guest = start - end; + } +#endif return 0; } -int v3_vnet_send_pkt(struct v3_vnet_pkt * pkt) { - +int v3_vnet_send_pkt(struct v3_vnet_pkt * pkt, void *private_data) { PrintDebug("In Vnet Send: pkt size: %d\n", pkt->size); - if (handle_one_pkt(pkt) != -1) { + if (handle_one_pkt(pkt, private_data) != -1) { PrintDebug("VNET: send one packet! pt length %d\n", pkt->size); } else { PrintDebug("VNET: Fail to forward one packet, discard it!\n"); @@ -406,54 +484,47 @@ int v3_vnet_add_dev(struct v3_vm_info *vm,uint8_t mac[6], int (*netif_input)(struct v3_vm_info * vm, struct v3_vnet_pkt * pkt, void * private_data), void * priv_data){ struct vnet_dev * new_dev = NULL; + unsigned long flags; + int dev_id; + flags = v3_lock_irqsave(vnet_state.lock); + new_dev = find_dev_by_mac(mac); - PrintDebug("VNET: register device\n"); - if (new_dev) { PrintDebug("VNET: register device: Already has device with the same mac\n"); - return -1; + dev_id = -1; + goto exit; } new_dev = (struct vnet_dev *)V3_Malloc(sizeof(struct vnet_dev)); if (new_dev == NULL) { PrintError("VNET: Malloc fails\n"); - return -1; + dev_id = -1; + goto exit; } memcpy(new_dev->mac_addr, mac, 6); new_dev->input = netif_input; new_dev->private_data = priv_data; new_dev->vm = vm; - - PrintDebug("VNET: register device new_dev22 %p\n", (void *)new_dev); list_add(&(new_dev->node), &(vnet_state.devs)); vnet_state.num_devs ++; new_dev->dev_id = vnet_state.num_devs; + dev_id = new_dev->dev_id; - return 0; -} - -#if 0 -static int v3_vnet_pkt_process() { - struct v3_vnet_pkt * pkt = NULL; + PrintDebug("Vnet: Add Device: dev_id %d, input : %p, private_data %p\n", + new_dev->dev_id, new_dev->input, new_dev->private_data); - while ((pkt = (struct v3_vnet_pkt *)v3_dequeue(vnet_state.inpkt_q)) != NULL) { - if (handle_one_pkt(pkt) != -1) { - PrintDebug("VNET: vnet_check: handle one packet! pt length %d\n", (int)pkt->size); - } else { - PrintDebug("VNET: vnet_check: Fail to forward one packet, discard it!\n"); - } +exit: - V3_Free(pkt); // be careful here - } - - return 0; + v3_unlock_irqrestore(vnet_state.lock, flags); + + return dev_id; } -#endif + int V3_init_vnet() { @@ -471,7 +542,6 @@ int V3_init_vnet() { PrintDebug("VNET: Locks initiated\n"); - /*initial pkt receiving queue */ vnet_state.inpkt_q = v3_create_queue(); v3_init_queue(vnet_state.inpkt_q); PrintDebug("VNET: Receiving queue initiated\n");