Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Update on Vnet and Virtio Nic
Lei Xia [Mon, 25 Jan 2010 20:02:57 +0000 (14:02 -0600)]
Kconfig
palacios/include/palacios/vmm_vnet.h
palacios/src/devices/lnx_virtio_nic.c
palacios/src/palacios/vmm_vnet.c

diff --git a/Kconfig b/Kconfig
index 4f43d7d..79e6cc1 100644 (file)
--- a/Kconfig
+++ b/Kconfig
@@ -108,6 +108,13 @@ config VNET
         help
           Enable the Vnet in Palacios
 
+config DEBUG_VNET
+        depends on VNET
+        bool "Enable Vnet Debug in Palacios"
+        default n
+        help
+          Enable the Vnet Debug in Palacios
+
 config BUILT_IN_STDLIB
        bool "Enable Built in versions of stdlib functions"
        default n
index c94c6c6..90e3ca1 100644 (file)
@@ -36,7 +36,7 @@
 #define ETHERNET_DATA_MAX   1500
 #define ETHERNET_PACKET_LEN (ETHERNET_HEADER_LEN + ETHERNET_DATA_MAX)
 
-typedef enum {MAC_ANY, MAC_NOT, MAC_NONE, MAC_EMPTY} mac_type_t; //for 'src_mac_qual' and 'dst_mac_qual'
+typedef enum {MAC_ANY, MAC_NOT, MAC_NONE} mac_type_t; //for 'src_mac_qual' and 'dst_mac_qual'
 typedef enum {LINK_INTERFACE, LINK_EDGE, LINK_ANY} link_type_t; //for 'type' and 'src_type' in struct routing
 typedef enum {TCP_TYPE, UDP_TYPE, NONE_TYPE} prot_type_t;
 
@@ -103,7 +103,7 @@ struct vnet_if_device {
 
 
 struct vnet_if_link {
-    prot_type_t pro_type; //protocal type of this link
+    prot_type_t pro_type; //transport layer protocal type of this link
     unsigned long dest_ip;
     uint16_t dest_port;
 
@@ -130,12 +130,20 @@ struct link_entry {
 
 int v3_vnet_send_rawpkt(uchar_t *buf, int len, void *private_data);
 int v3_vnet_send_udppkt(uchar_t *buf, int len, void *private_data);
-//int vnet_register_device(struct vm_device *vdev, 
-//                      char *dev_name, 
-//                      uchar_t mac[6], 
-//                      int (*netif_input)(uchar_t * pkt, uint_t size, void *private_data), 
-//                      void *data);
-//int vnet_unregister_device(char *dev_name);
+int vnet_register_device(struct vm_device *vdev, 
+                        char *dev_name, 
+                        uchar_t mac[6], 
+                        int (*netif_input)(uchar_t * pkt, uint_t size, void *private_data), 
+                        void *data);
+
+int vnet_add_route_entry(char src_mac[6],
+                               char dest_mac[6],
+                               int src_mac_qual,
+                               int dest_mac_qual,
+                               int link_idx,
+                               link_type_t link_type,
+                               int src_link_idx,
+                               link_type_t src_link_type);
 
 int v3_vnet_pkt_process(); 
 
index a21bdb8..4874b73 100644 (file)
@@ -9,11 +9,13 @@
  *
  * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu>
  * Copyright (c) 2008, Lei Xia <lxia@northwestern.edu>
+ * Copyright (c) 2008, Cui Zheng <cuizheng@cs.unm.edu>
  * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
  * All rights reserved.
  *
  * Author: Jack Lange <jarusl@cs.northwestern.edu>
  *               Lei Xia <lxia@northwestern.edu>
+ *             Cui Zheng <cuizheng@cs.unm.edu>
  *              
  *
  * This is free software.  You are permitted to use,
@@ -25,6 +27,7 @@
 #include <devices/lnx_virtio_pci.h>
 #include <palacios/vm_guest_mem.h>
 #include <palacios/vmm_sprintf.h>
+#include <palacios/vmm_vnet.h>
 
 #include <devices/pci.h>
 
@@ -71,7 +74,7 @@ struct virtio_net_hdr {
 }__attribute__((packed));
 
        
-#define QUEUE_SIZE 256
+#define QUEUE_SIZE 1024
 #define CTRL_QUEUE_SIZE 64
 #define ETH_ALEN 6
 
@@ -105,13 +108,19 @@ struct virtio_net_state {
     struct list_head dev_link;
 };
 
-#if 1
-//Temporarly for debug
+
+#ifdef CONFIG_DEBUG_VIRTIO_NET
+
 static void print_packet(uchar_t *pkt, int size) {
     PrintDebug("Virtio Nic: print_data_packet: size: %d\n", size);
     v3_hexdump(pkt, size, NULL, 0);
 }
 
+#endif
+
+#if 0
+//Temporarly for debug
+
 static struct virtio_net_state *temp_net_states[3]; 
 static int net_idx = 0;
 
@@ -119,8 +128,12 @@ static int __virtio_dev_send(uchar_t * buf, uint32_t size, void *private_data);
 
 static int send(uint8_t * buf, uint32_t count, void * private_data, struct vm_device *dest_dev)
 {
-   PrintDebug("Virito NIC: In sending stub, guest %p\n", private_data);
-   print_packet(buf, count);
+   PrintDebug("Virito NIC: In sending stub, guest %p, count %d\n", private_data, count);
+
+#ifdef CONFIG_DEBUG_VIRTIO_NET
+   print_packet(buf, 20);
+#endif
+
    struct virtio_net_state *virtio_state = (struct virtio_net_state *)private_data;
 
    if (virtio_state == temp_net_states[0])
@@ -191,8 +204,8 @@ static int pkt_write(struct virtio_net_state * virtio, struct vring_desc * buf_d
     }
 
     PrintDebug("Length=%d\n", buf_desc->length);
-    PrintDebug("Buffer Descriptor (ptr=%p) gpa=%p, len=%d, flags=%x, next=%d, buf address: %p, send address: %p\n", buf_desc, 
-              (void *)(buf_desc->addr_gpa), buf_desc->length, buf_desc->flags, buf_desc->next, buf, virtio->net_ops->send);
+    //PrintDebug("Buffer Descriptor (ptr=%p) gpa=%p, len=%d, flags=%x, next=%d, buf address: %p, send address: %p\n", buf_desc, 
+              //(void *)(buf_desc->addr_gpa), buf_desc->length, buf_desc->flags, buf_desc->next, buf, virtio->net_ops->send);
 
     if (virtio->net_ops->send(buf, len, (void *)virtio, NULL) == -1) {
        return -1;
@@ -227,11 +240,8 @@ static int copy_data_to_desc(struct virtio_net_state * virtio_state, struct vrin
     }
 
     len = (desc->length < buf_len)?desc->length:buf_len;
-
     memcpy(desc_buf, buf, len);
 
-    PrintDebug("Length=%d\n", len);
-
     return len;
 }
 
@@ -245,10 +255,10 @@ static int send_pkt_to_guest(struct virtio_net_state * virtio, uchar_t * buf, ui
     uint32_t data_len = size;
     uint32_t offset = 0;
 
-    PrintDebug("VIRTIO NIC:  Handle RX: cur_index=%d (mod=%d), avail_index=%d\n", 
-              q->cur_avail_idx, q->cur_avail_idx % q->queue_size, q->avail->index);
+    //PrintDebug("VIRTIO NIC:  Handle RX: cur_index=%d (mod=%d), avail_index=%d\n", 
+              //q->cur_avail_idx, q->cur_avail_idx % q->queue_size, q->avail->index);
 
-    PrintDebug("VIRTIO NIC:  sending packet to net_state %p, size:%d", virtio, size);
+    PrintError("VIRTIO NIC:  sending packet to net_state %p, size:%d", virtio, size);
 
     if (!raw) {
        data_len -= hdr_len;
@@ -262,19 +272,18 @@ static int send_pkt_to_guest(struct virtio_net_state * virtio, uchar_t * buf, ui
        return -1;
     }
 
-    
     if (q->cur_avail_idx < q->avail->index) {
        addr_t hdr_addr = 0;
        uint16_t hdr_idx = q->avail->ring[q->cur_avail_idx % q->queue_size];
        uint16_t buf_idx = 0;
        struct vring_desc * hdr_desc = NULL;
 
-       PrintDebug("Descriptor index=%d\n", q->cur_avail_idx % q->queue_size);
+       //PrintDebug("Descriptor index=%d\n", q->cur_avail_idx % q->queue_size);
 
        hdr_desc = &(q->desc[hdr_idx]);
 
-       PrintDebug("Header Descriptor (ptr=%p) gpa=%p, len=%d, flags=%x, next=%d\n", hdr_desc, 
-                  (void *)(hdr_desc->addr_gpa), hdr_desc->length, hdr_desc->flags, hdr_desc->next);    
+       //PrintDebug("Header Descriptor (ptr=%p) gpa=%p, len=%d, flags=%x, next=%d\n", hdr_desc, 
+                  //(void *)(hdr_desc->addr_gpa), hdr_desc->length, hdr_desc->flags, hdr_desc->next);  
 
        if (guest_pa_to_host_va(virtio->virtio_dev->vm, hdr_desc->addr_gpa, &(hdr_addr)) == -1) {
            PrintError("Could not translate receive buffer address\n");
@@ -300,9 +309,8 @@ static int send_pkt_to_guest(struct virtio_net_state * virtio, uchar_t * buf, ui
            //       if there still is some data left
            //buf_desc->flags = VIRTIO_NEXT_FLAG;
         
-           
-           PrintError("JACK: copying packet to up desc (len = %d)\n", data_len - offset);
-           v3_hexdump(buf + offset, data_len - offset, NULL, 0);
+           //PrintError("JACK: copying packet to up desc (len = %d)\n", data_len - offset);
+           //v3_hexdump(buf + offset, data_len - offset, NULL, 0);
 
            len = copy_data_to_desc(virtio, buf_desc, buf + offset, data_len - offset);
            
@@ -314,7 +322,7 @@ static int send_pkt_to_guest(struct virtio_net_state * virtio, uchar_t * buf, ui
            }
 
            buf_desc->length = len;  // TODO: do we need this?
-           PrintError("JACK: setting buffer descriptor length to %d)\n", buf_desc->length);
+           //PrintError("JACK: setting buffer descriptor length to %d)\n", buf_desc->length);
        }
 
        
@@ -331,8 +339,6 @@ static int send_pkt_to_guest(struct virtio_net_state * virtio, uchar_t * buf, ui
        virtio->virtio_cfg.pci_isr = 0x1;
     }
 
-
-    PrintError("\n\n\n\n");
     return offset;
 }
 
@@ -378,8 +384,8 @@ static int handle_pkt_tx(struct virtio_net_state * virtio_state)
     //struct virtio_net_state *virtio = (struct virtio_net_state *)dev->private_data;    
     struct virtio_queue * q = &(virtio_state->tx_vq);
 
-    PrintDebug("VIRTIO NIC pkt_tx: cur_index=%d (mod=%d), avail_index=%d\n", 
-              q->cur_avail_idx, q->cur_avail_idx % q->queue_size, q->avail->index);
+    //PrintDebug("VIRTIO NIC pkt_tx: cur_index=%d (mod=%d), avail_index=%d\n", 
+             // q->cur_avail_idx, q->cur_avail_idx % q->queue_size, q->avail->index);
 
     struct virtio_net_hdr * hdr = NULL;
 
@@ -391,30 +397,29 @@ static int handle_pkt_tx(struct virtio_net_state * virtio_state)
        uint32_t req_len = 0;
        int i = 0;
 
-       PrintDebug("Descriptor Count=%d, index=%d\n", desc_cnt, q->cur_avail_idx % q->queue_size);
+       //PrintDebug("Descriptor Count=%d, index=%d\n", desc_cnt, q->cur_avail_idx % q->queue_size);
 
        hdr_desc = &(q->desc[desc_idx]);
 
-       PrintDebug("Header Descriptor (ptr=%p) gpa=%p, len=%d, flags=%x, next=%d\n", hdr_desc, 
-                  (void *)(hdr_desc->addr_gpa), hdr_desc->length, hdr_desc->flags, hdr_desc->next);    
+       //PrintDebug("Header Descriptor (ptr=%p) gpa=%p, len=%d, flags=%x, next=%d\n", hdr_desc, 
+                  //(void *)(hdr_desc->addr_gpa), hdr_desc->length, hdr_desc->flags, hdr_desc->next);  
 
        if (guest_pa_to_host_va(virtio_state->virtio_dev->vm, hdr_desc->addr_gpa, &(hdr_addr)) == -1) {
            PrintError("Could not translate block header address\n");
            return -1;
        }
 
-       //memcpy(&hdr, (void *)hdr_addr, sizeof(struct virtio_net_hdr));
        hdr = (struct virtio_net_hdr*)hdr_addr;
        
-       PrintDebug("NIC Op Hdr (ptr=%p) header len =%x\n", (void *)hdr_addr, (int)hdr->hdr_len);
+       //PrintDebug("NIC Op Hdr (ptr=%p) header len =%x\n", (void *)hdr_addr, (int)hdr->hdr_len);
 
        desc_idx = hdr_desc->next;
        
        for (i = 0; i < desc_cnt - 1; i++) {    
            struct vring_desc * buf_desc = &(q->desc[desc_idx]);
 
-           PrintDebug("Buffer Descriptor (ptr=%p) gpa=%p, len=%d, flags=%x, next=%d\n", buf_desc, 
-                      (void *)(buf_desc->addr_gpa), buf_desc->length, buf_desc->flags, buf_desc->next);
+           //PrintDebug("Buffer Descriptor (ptr=%p) gpa=%p, len=%d, flags=%x, next=%d\n", buf_desc, 
+                      //(void *)(buf_desc->addr_gpa), buf_desc->length, buf_desc->flags, buf_desc->next);
 
            if (pkt_write(virtio_state, buf_desc) == -1) {
                PrintError("Error handling nic operation\n");
@@ -433,7 +438,7 @@ static int handle_pkt_tx(struct virtio_net_state * virtio_state)
     }
 
     if (!(q->avail->flags & VIRTIO_NO_IRQ_FLAG)) {
-       PrintDebug("Raising IRQ %d\n",  virtio_state->pci_dev->config_header.intr_line);
+       //PrintDebug("Raising IRQ %d\n",  virtio_state->pci_dev->config_header.intr_line);
        v3_pci_raise_irq(virtio_state->virtio_dev->pci_bus, 0, virtio_state->pci_dev);
        virtio_state->virtio_cfg.pci_isr = 0x1;
     }
@@ -547,10 +552,10 @@ static int virtio_io_write(uint16_t port, void * src, uint_t length, void * priv
            {
                uint16_t queue_idx = *(uint16_t *)src;     
                
-               PrintDebug("Handling Kick\n");
+               //PrintDebug("Handling Kick\n");
                
                if (queue_idx == 0){
-                   PrintError("receive queue notification\n");
+                   PrintDebug("receive queue notification 0, packet get by Guest\n");
                } else if (queue_idx == 1){
                    if (handle_pkt_tx(virtio) == -1) {
                        PrintError("Could not handle NIC Notification\n");
@@ -798,6 +803,78 @@ static int connect_fn(struct guest_info * info,
     return 0;
 }
 
+#if 1 
+//temporary interface between Virtio-NIC and Vnet
+//Treat vnet as backend, and virtio nic as frontend
+
+//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 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);
+
+#ifdef CONFIG_DEBUG_VIRTIO_NET
+    print_packet(buf, len);
+#endif
+
+    v3_vnet_send_rawpkt(buf, len, private_data);
+    return 0;
+}
+
+//used to send packet to guest by a virtio nic
+static int vnet_receive(uint8_t * buf, uint32_t count, void * private_data, struct vm_device *src_dev){
+
+    return 0;
+}
+
+static int virtio_input(uchar_t * buf, uint_t len, void * private_data){
+    PrintDebug("Virito NIC: In virtio_input: guest net state %p\n", private_data);
+
+#ifdef CONFIG_DEBUG_VIRTIO_NET
+    print_packet(buf, len);
+#endif
+
+    return __virtio_dev_send(buf, len, private_data);
+}
+
+
+//register a virtio device to the vnet as backend
+void register_virtio_to_vnet(struct vm_device  *dev, 
+                                               char *dev_name,
+                                               uchar_t mac[6]){
+    struct virtio_net_state * net_state  = (struct virtio_net_state *)V3_Malloc(sizeof(struct virtio_net_state));
+    memset(net_state, 0, sizeof(struct virtio_net_state));
+
+    struct virtio_dev_state *virtio_state =  (struct virtio_dev_state *)dev->private_data;
+
+    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;
+
+    register_dev(virtio_state, net_state);
+       
+    PrintDebug("Virtio NIC After register Device %s: queue size: %d, %d\n", dev->name,
+              net_state->rx_vq.queue_size, net_state->tx_vq.queue_size);
+
+    PrintDebug("VNET: connect virtio nic state %p to vnet\n", net_state);
+
+    //add a device link to link table
+    int idx = vnet_register_device(dev, dev_name, mac, &virtio_input, net_state);
+
+    uchar_t srcmac[6] = {0x00,0x02,0x55,0x67,0x42,0x39};
+    uchar_t dstmac[6] = {0xff,0xff,0xff,0xff,0xff,0xff};
+    uchar_t zeromac[6] = {0,0,0,0,0,0};
+
+    vnet_add_route_entry(zeromac, dstmac, MAC_ANY, MAC_NONE, idx, LINK_INTERFACE, -1, LINK_INTERFACE);
+    if (idx == 0)
+       vnet_add_route_entry(zeromac, srcmac, MAC_ANY, MAC_NONE, idx, LINK_INTERFACE, -1, LINK_INTERFACE);
+    if (idx == 1)
+       vnet_add_route_entry(srcmac, zeromac, MAC_NONE, MAC_ANY, idx, LINK_INTERFACE, -1, LINK_INTERFACE);
+               
+}
+
+#endif
 
 static int virtio_init(struct guest_info * vm, v3_cfg_tree_t * cfg) {
     struct vm_device * pci_bus = v3_find_dev(vm, v3_cfg_val(cfg, "bus"));
@@ -831,8 +908,8 @@ static int virtio_init(struct guest_info * vm, v3_cfg_tree_t * cfg) {
 
 
     //for temporary testing, add a backend
-    #if 1
-   
+#if 0
+       
     struct virtio_net_state * net_state  = (struct virtio_net_state *)V3_Malloc(sizeof(struct virtio_net_state));
     memset(net_state, 0, sizeof(struct virtio_net_state));
 
@@ -849,9 +926,16 @@ static int virtio_init(struct guest_info * vm, v3_cfg_tree_t * cfg) {
     temp_net_states[net_idx ++] = net_state;
 
     PrintDebug("Net_states: 0: %p, 1: %p, 2: %p\n", temp_net_states[0], temp_net_states[1], temp_net_states[2]);
-       
-    #endif
 
+#endif
+
+#if 1  //test interface between vnet & virtio-nic
+
+    uchar_t mac[6] = {0,0,0,0,0,0};
+    register_virtio_to_vnet(dev, name,mac);
+
+#endif
+       
     return 0;
 }
 
index bf3b2c6..d2daa7e 100644 (file)
@@ -38,16 +38,16 @@ struct ethernet_pkt {
     uint16_t type;
     struct udp_link_header ext_hdr; //possible externel header to applied to data before sent
     char data[ETHERNET_PACKET_LEN];
-};
+}__attribute__((packed));
 
 
 // 14 (ethernet frame) + 20 bytes
 struct in_pkt_header {
-    char ethernetdest[6];
-    char ethernetsrc[6];
-    unsigned char ethernettype[2]; //layer 3 protocol type
+    uchar_t ethernetdest[6];
+    uchar_t ethernetsrc[6];
+    uchar_t ethernettype[2]; //layer 3 protocol type
     char ip[20];
-};
+}__attribute__((packed));
 
 #define VNET_INITAB_HCALL 0xca00  // inital hypercall id
 
@@ -60,12 +60,12 @@ static const uint_t hash_key_size = 16;
 struct link_table {
     struct link_entry * links[MAX_LINKS];
     uint16_t size;
-};
+}__attribute__((packed));
 
 struct routing_table {
     struct routing_entry * routes[MAX_ROUTES];
     uint16_t size;
-};
+}__attribute__((packed));
 
 static struct link_table g_links;
 static struct routing_table g_routes;
@@ -88,27 +88,6 @@ struct route_cache_entry {
 // the route cache
 static struct hashtable * g_route_cache; 
 
-
-static void print_packet(uchar_t *pkt, int size) {
-    PrintDebug("Vnet: print_data_packet: size: %d\n", size);
-    v3_hexdump(pkt, size, NULL, 0);
-}
-
-#if 0
-static void print_packet_addr(char * pkt) {
-    PrintDebug("Vnet: print_packet_destination_addr: ");
-    v3_hexdump(pkt + 8, 6, NULL, 0);
-    
-    PrintDebug("Vnet: print_packet_source_addr: ");
-    v3_hexdump(pkt + 14, 6, NULL, 0);
-}
-
-static void print_device_addr(char * ethaddr) {
-    PrintDebug("Vnet: print_device_addr: ");
-    v3_hexdump(ethaddr, 6, NULL, 0);
-} 
-#endif
-
 static uint16_t ip_xsum(struct ip_header *ip_hdr, int hdr_len){
     long sum = 0;
 
@@ -238,6 +217,12 @@ static int look_into_cache(route_hashkey_t hashkey, int * matches) {
 }
 
 #ifdef CONFIG_DEBUG_VNET
+
+static void print_packet(uchar_t *pkt, int size) {
+    PrintDebug("Vnet: print_data_packet: size: %d\n", size);
+    v3_hexdump(pkt, size, NULL, 0);
+}
+
 static inline uint8_t hex_nybble_to_nybble(const uint8_t hexnybble) {
     uint8_t x = toupper(hexnybble);
 
@@ -262,10 +247,35 @@ static inline void string_to_mac(const char *str, uint8_t mac[6]) {
 }
 
 static inline void mac_to_string(char mac[6], char * buf) {
-    snprintf(buf, 20, "%x:%x:%x:%x:%x:%x", 
+    snprintf(buf, 20, "%02x:%02x:%02x:%02x:%02x:%02x", 
             mac[0], mac[1], mac[2],
             mac[3], mac[4], mac[5]);
 }
+
+static void dump_routes(struct routing_entry **route_tables) {
+    char dest_str[18];
+    char src_str[18];
+    struct routing_entry *route = NULL;
+    int i;
+
+    PrintDebug("\nVnet: route table dump start =====\n");
+
+    for(i = 0; i < MAX_ROUTES; i++) {
+        if (route_tables[i] != NULL){
+            route = route_tables[i];
+    
+            mac_to_string(route->src_mac, src_str);  
+            mac_to_string(route->dest_mac, dest_str);
+
+            PrintDebug("route: %d\n", i);
+            PrintDebug("SRC(%s), DEST(%s), src_mac_qual(%d), dst_mac_qual(%d)\n", src_str, dest_str, route->src_mac_qual, route->dest_mac_qual);
+            PrintDebug("Src_Link(%d), src_type(%d), dst_link(%d), dst_type(%d)\n\n", route->src_link_idx, route->src_type, route->link_idx, route->link_type);
+        }
+    }
+
+    PrintDebug("\nVnet: route table dump end =====\n");
+}
+
 #endif
 
 static int __add_link_entry(struct link_entry * link) {
@@ -301,24 +311,24 @@ static int __add_route_entry(struct routing_entry * route) {
 }
 
 
-static int vnet_add_route_entry(char src_mac[6],
+int vnet_add_route_entry(char src_mac[6],
                                char dest_mac[6],
                                int src_mac_qual,
                                int dest_mac_qual,
                                int link_idx,
                                link_type_t link_type,
-                               int src,
-                               link_type_t src_type) {
+                               int src_link_idx,
+                               link_type_t src_link_type) {
     struct routing_entry * new_route = (struct routing_entry *)V3_Malloc(sizeof(struct routing_entry));
     int idx = -1;
 
     memset(new_route, 0, sizeof(struct routing_entry));
 
-    if ((src_mac_qual != MAC_ANY) && (src_mac_qual != MAC_NONE)) {
+    if ((src_mac_qual != MAC_ANY)) {
         memcpy(new_route->src_mac, src_mac, 6);
     }
            
-    if ((dest_mac_qual != MAC_ANY) && (dest_mac_qual != MAC_NONE)) {
+    if ((dest_mac_qual != MAC_ANY)) {
         memcpy(new_route->dest_mac, dest_mac, 6);
     }
            
@@ -326,8 +336,8 @@ static int vnet_add_route_entry(char src_mac[6],
     new_route->dest_mac_qual = dest_mac_qual;
     new_route->link_idx= link_idx;
     new_route->link_type = link_type;
-    new_route->src_link_idx = src;
-    new_route->src_type = src_type;
+    new_route->src_link_idx = src_link_idx;
+    new_route->src_type = src_link_type;
 
     if ((idx = __add_route_entry(new_route)) == -1) {
        PrintError("Could not add route entry\n");
@@ -339,6 +349,7 @@ static int vnet_add_route_entry(char src_mac[6],
     return idx;
 }
 
+#if 0
 static void * __delete_link_entry(int index) {
     struct link_entry * link = NULL;
     void * ret = NULL;
@@ -444,140 +455,101 @@ static int vnet_delete_route_entry_by_addr(char src_mac[6],
     
     return __delete_route_entry(index);
 }
+#endif
 
 static int match_route(uint8_t * src_mac, 
                       uint8_t * dst_mac, 
                       link_type_t src_type, 
                       int src_index, 
-                      int * matches) { 
-    int values[MAX_ROUTES];
+                      int * matches) {
     int matched_routes[MAX_ROUTES];
-    
     int num_matches = 0;
     int i;
-    int max = 0;
-    int no = 0;
-    int exact_match = 0;
+    struct routing_entry *route = NULL; 
+
+#ifdef CONFIG_DEBUG_VNET
+    char dest_str[18];
+    char src_str[18];
+    
+    mac_to_string(src_mac, src_str);  
+    mac_to_string(dst_mac, dest_str);
+    
+    PrintDebug("Vnet: match_route. pkt: SRC(%s), DEST(%s)\n", src_str, dest_str);
+
+    dump_routes(g_routes.routes);
+#endif
 
     for(i = 0; i < MAX_ROUTES; i++) {
-       if (g_routes.routes[i] != NULL){
-           if ( (g_routes.routes[i]->src_type != LINK_ANY) &&
-                ( (g_routes.routes[i]->src_type != src_type) ||
-                  ( (g_routes.routes[i]->src_link_idx != src_index) &&
-                    (g_routes.routes[i]->src_link_idx != -1)))) {
-               PrintDebug("Vnet: MatchRoute: Source route is on and does not match\n");
-               continue;
-           }
+        if (g_routes.routes[i] != NULL){
+            route = g_routes.routes[i];
+
+            if(src_type == LINK_ANY && src_index == -1) {
+                if ((route->dest_mac_qual == MAC_ANY) &&
+                      (route->src_mac_qual == MAC_ANY)) {      
+                    matched_routes[num_matches] = i;
+                    num_matches++;
+                }
        
-           if ( (g_routes.routes[i]->dest_mac_qual == MAC_ANY) &&
-                (g_routes.routes[i]->src_mac_qual == MAC_ANY)) {      
+                if (memcmp((void *)&route->src_mac, (void *)src_mac, 6) == 0) {
+                    if (route->src_mac_qual !=  MAC_NOT) {
+                         if (route->dest_mac_qual == MAC_ANY) {
+                             matched_routes[num_matches] = i;
+                             num_matches++;
+                         } else if (route->dest_mac_qual != MAC_NOT &&
+                                     memcmp((void *)&route->dest_mac, (void *)dst_mac, 6) == 0) {
+                            matched_routes[num_matches] = i;
+                            num_matches++;
+                        }
+                    }
+                }
 
-               matched_routes[num_matches] = i;
-               values[num_matches] = 3;
-               num_matches++;
-           }
-       
-           if (memcmp((void *)&g_routes.routes[i]->src_mac, (void *)src_mac, 6) == 0) {
-               if (g_routes.routes[i]->src_mac_qual !=  MAC_NOT) {
-                   if (g_routes.routes[i]->dest_mac_qual == MAC_ANY) {
-                       matched_routes[num_matches] = i;
-                       values[num_matches] = 6;
-                       
-                       num_matches++;
-                   } else if (memcmp((void *)&g_routes.routes[i]->dest_mac, (void *)dst_mac, 6) == 0) {
-                       if (g_routes.routes[i]->dest_mac_qual != MAC_NOT) {   
-                           matched_routes[num_matches] = i;
-                           values[num_matches] = 8;    
-                           exact_match = 1;
-                           num_matches++;
-                       }
-                   }
-               }
-           }
-       
-           if (memcmp((void *)&g_routes.routes[i]->dest_mac, (void *)dst_mac, 6) == 0) {
-               if (g_routes.routes[i]->dest_mac_qual != MAC_NOT) {
-                   if (g_routes.routes[i]->src_mac_qual == MAC_ANY) {
-                       matched_routes[num_matches] = i;
-                       values[num_matches] = 6;
-                       
-                       num_matches++;
-                   } else if (memcmp((void *)&g_routes.routes[i]->src_mac, (void *)src_mac, 6) == 0) {
-                       if (g_routes.routes[i]->src_mac_qual != MAC_NOT) {
-                           if (exact_match == 0) {
-                               matched_routes[num_matches] = i;
-                               values[num_matches] = 8;
-                               num_matches++;
-                           }
-                       }
-                   }
-               }
-           }
+                if (memcmp((void *)&route->dest_mac, (void *)dst_mac, 6) == 0) {
+                    if (route->dest_mac_qual != MAC_NOT) {
+                        if (route->src_mac_qual == MAC_ANY) {
+                            matched_routes[num_matches] = i;
+                            num_matches++;
+                        } else if ((route->src_mac_qual != MAC_NOT) && 
+                                       (memcmp((void *)&route->src_mac, (void *)src_mac, 6) == 0)) {
+                            matched_routes[num_matches] = i;
+                            num_matches++;
+                        }
+                     }
+                }
+
+                if ((route->dest_mac_qual == MAC_NOT) &&
+                      (memcmp((void *)&route->dest_mac, (void *)dst_mac, 6) != 0)) {
+                    if (route->src_mac_qual == MAC_ANY) {
+                        matched_routes[num_matches] = i;           
+                        num_matches++;    
+                    } else if ((route->src_mac_qual != MAC_NOT) && 
+                                   (memcmp((void *)&route->src_mac, (void *)src_mac, 6) == 0)) {     
+                        matched_routes[num_matches] = i;     
+                        num_matches++;
+                     }
+                }
+
+                if ((route->src_mac_qual == MAC_NOT) &&
+                      (memcmp((void *)&route->src_mac, (void *)src_mac, 6) != 0)) {
+                    if (route->dest_mac_qual == MAC_ANY) {
+                        matched_routes[num_matches] = i;   
+                        num_matches++;
+                    } else if ((route->dest_mac_qual != MAC_NOT) &&
+                                   (memcmp((void *)&route->dest_mac, (void *)dst_mac, 6) == 0)) {
+                        matched_routes[num_matches] = i;
+                        num_matches++;
+                    }
+                }
+            }//end if src_type == Link_any
+        }      
+    }//end for
+
+    PrintDebug("Vnet: match_route: Matches=%d\n", num_matches);
        
-           if ( (g_routes.routes[i]->dest_mac_qual == MAC_NOT) &&
-                (memcmp((void *)&g_routes.routes[i]->dest_mac, (void *)dst_mac, 6) != 0)) {
-               if (g_routes.routes[i]->src_mac_qual == MAC_ANY) {
-                   matched_routes[num_matches] = i;
-                   values[num_matches] = 5;                
-                   num_matches++;    
-               } else if (memcmp((void *)&g_routes.routes[i]->src_mac, (void *)src_mac, 6) == 0) {
-                   if (g_routes.routes[i]->src_mac_qual != MAC_NOT) {      
-                       matched_routes[num_matches] = i;
-                       values[num_matches] = 7;                      
-                       num_matches++;
-                   }
-               }
-           }
-           
-           if ( (g_routes.routes[i]->src_mac_qual == MAC_NOT) &&
-                (memcmp((void *)&g_routes.routes[i]->src_mac, (void *)src_mac, 6) != 0)) {
-               if (g_routes.routes[i]->dest_mac_qual == MAC_ANY) {
-                   matched_routes[num_matches] = i;
-                   values[num_matches] = 5;        
-                   num_matches++;
-               } else if (memcmp((void *)&g_routes.routes[i]->dest_mac, (void *)dst_mac, 6) == 0) {
-                   if (g_routes.routes[i]->dest_mac_qual != MAC_NOT) { 
-                       matched_routes[num_matches] = i;
-                       values[num_matches] = 7;
-                       num_matches++;
-                   }
-               }
-           }
-       }
-    } // end for
-    
-    for (i = 0; i < MAX_ROUTES; i++) {
-       if ( (memcmp((void *)&g_routes.routes[i]->src_mac, (void *)src_mac, 6) == 0) &&
-            (g_routes.routes[i]->dest_mac_qual == MAC_NONE) &&
-            ( (g_routes.routes[i]->src_type == LINK_ANY) ||
-              ( (g_routes.routes[i]->src_type == src_type) &&
-                ( (g_routes.routes[i]->src_link_idx == src_index) ||
-                  (g_routes.routes[i]->src_link_idx == -1))))) {
-           matched_routes[num_matches] = i;
-           values[num_matches] = 4;
-           PrintDebug("Vnet: MatchRoute: We matched a default route (%d)\n", i);
-           num_matches++;
-       }
-    }
-    
-    //If many rules have been matched, we choose one which has the highest value rating
-    if (num_matches == 0) {
-       return 0;
-    }
-    
     for (i = 0; i < num_matches; i++) {
-       if (values[i] > max) {
-           no = 0;
-           max = values[i];
-           matches[no] = matched_routes[i];
-           no++;
-       } else if (values[i] == max) {
-           matches[no] = matched_routes[i];
-           no++;
-       }
+        matches[i] = matched_routes[i];
     }
     
-    return no;
+    return num_matches;
 }
 
 static int handle_one_pkt(struct ethernet_pkt *pkt) {
@@ -623,6 +595,10 @@ static int handle_one_pkt(struct ethernet_pkt *pkt) {
     }
     
     PrintDebug("Vnet: HandleDataOverLink: Matches=%d\n", num_matched_routes);
+
+    if (num_matched_routes == 0) {
+        return -1;
+    }
     
     for (i = 0; i < num_matched_routes; i++) {//send packet to all destinations
         int route_index = -1;
@@ -631,51 +607,49 @@ static int handle_one_pkt(struct ethernet_pkt *pkt) {
         struct link_entry * link = NULL;
 
         route_index = matches[i];
-       
-        PrintDebug("Vnet: HandleDataOverLink: Forward packet from link according to Route entry %d\n", route_index);
-       
         link_index = g_routes.routes[route_index]->link_idx;
 
-        if ((link_index < 0) || 
-            (link_index > MAX_LINKS) || 
+        if ((link_index < 0) || (link_index > MAX_LINKS) || 
             (g_links.links[link_index] == NULL)) {
             continue;
         }
        
         link = g_links.links[link_index];
         pkt_len = pkt->size;
-        if (g_routes.routes[route_index]->link_type == LINK_EDGE) {
+        if (link->type == LINK_EDGE) {
 
              //apply the header in the beginning of the packet to be sent
             if (link->dst_link->pro_type == UDP_TYPE) {
                 struct udp_link_header *hdr = &(link->dst_link->vnet_header);
                 struct ip_header *ip = &hdr->ip_hdr;
                 struct udp_header *udp = &hdr->udp_hdr;
-                  udp->len = pkt_len + sizeof(struct udp_header);
-                  ip->total_len = pkt_len + sizeof(struct udp_header) + sizeof(struct ip_header);
-                  ip->cksum = ip_xsum(ip, sizeof(struct ip_header));
+                 udp->len = pkt_len + sizeof(struct udp_header);
+                 ip->total_len = pkt_len + sizeof(struct udp_header) + sizeof(struct ip_header);
+                 ip->cksum = ip_xsum(ip, sizeof(struct ip_header));
                
                 int hdr_size = sizeof(struct udp_link_header);
                 memcpy(&pkt->ext_hdr, hdr, hdr_size);
 
                 pkt_len += hdr_size;
                 if ((link->dst_link->input((uchar_t *)&pkt->ext_hdr, pkt_len, link->dst_link->private_data)) != pkt_len) {
-                    PrintDebug("VNET: Packet not sent properly\n");
-                    return -1;
+                    PrintDebug("VNET: Packet not sent properly to link: %d\n", link_index);
+                    continue;
                 }
             }else {
                 PrintDebug("VNET: Link protocol type not support\n");
-                return -1;
+                continue;
             }
-        } else if (g_routes.routes[route_index]->link_type == LINK_INTERFACE) {
+        } else if (link->type == LINK_INTERFACE) {
             if ((link->dst_dev->input(pkt->data, pkt_len, link->dst_dev->private_data)) != pkt_len) {
-                  PrintDebug("VNET: Packet not sent properly\n");
-                  return -1;
+                PrintDebug("VNET: Packet not sent properly to link: %d\n", link_index);
+                continue;
             }
         } else {
-            PrintDebug("Vnet: Wrong Edge type\n");
-            return -1;
+            PrintDebug("Vnet: Wrong Edge type of link: %d\n", link_index);
+            continue;
         }
+
+        PrintDebug("Vnet: HandleDataOverLink: Forward packet according to Route entry %d to link %d\n", route_index, link_index);
     }
     
     return 0;
@@ -695,7 +669,10 @@ static int send_ethernet_pkt(uchar_t *data, int len) {
     ethernet_packet_init(pkt, data, len);  //====here we copy sending data once 
        
     PrintDebug("VNET: vm_send_pkt: transmitting packet: (size:%d)\n", (int)pkt->size);
+
+#ifdef CONFIG_DEBUG_VNET
     print_packet((char *)data, len);
+#endif
     
     v3_enqueue(g_inpkt_q, (addr_t)pkt);
 
@@ -740,14 +717,12 @@ int vnet_register_device(struct vm_device * vdev,
     struct vnet_if_device * if_dev;
 
     int idx = search_device(dev_name);
-
     if (idx != -1) {
        PrintDebug("VNET: register device: Already has device with the name %s\n", dev_name);
        return -1;
     }
     
-    if_dev = (struct vnet_if_device *)(sizeof(struct vnet_if_device));
-    
+    if_dev = (struct vnet_if_device *)V3_Malloc(sizeof(struct vnet_if_device)); 
     if (if_dev == NULL) {
        PrintError("VNET: Malloc fails\n");
        return -1;
@@ -759,15 +734,12 @@ int vnet_register_device(struct vm_device * vdev,
     if_dev->input = netif_input;
     if_dev->private_data = data;
 
-    struct link_entry * link = (struct link_entry *)(sizeof(struct link_entry));
-
+    struct link_entry * link = (struct link_entry *)V3_Malloc(sizeof(struct link_entry));
     link->type = LINK_INTERFACE;
     link->dst_dev = if_dev;
 
     idx = __add_link_entry(link);
 
-    PrintDebug("VNET: Add device %s to link table, idx %d", dev_name, idx);
-    
     return idx;
 }
 
@@ -798,25 +770,21 @@ static int vnet_unregister_device(char * dev_name) {
 int v3_vnet_pkt_process() {
     struct ethernet_pkt * pkt;
 
-    PrintDebug("VNET: In vnet_check\n");
-       
     while ((pkt = (struct ethernet_pkt *)v3_dequeue(g_inpkt_q)) != NULL) {
-       PrintDebug("VNET: In vnet_check: pt length %d, pt type %d\n", (int)pkt->size, (int)pkt->type);
-       v3_hexdump(pkt->data, pkt->size, NULL, 0);
-       
-       if (handle_one_pkt(pkt)) {
-           PrintDebug("VNET: vnet_check: handle one packet!\n");  
-       } else {
-           PrintError("VNET: vnet_check: fail to forward one packet, discard it!\n"); 
-       }
+        PrintDebug("VNET: In vnet_check: pt length %d, pt type %d\n", (int)pkt->size, (int)pkt->type);
+
+        if (handle_one_pkt(pkt) != -1) {
+            PrintDebug("VNET: vnet_check: handle one packet!\n");  
+        } else {
+            PrintDebug("VNET: vnet_check: Fail to forward one packet, discard it!\n"); 
+        }
        
-       V3_Free(pkt); // be careful here
+        V3_Free(pkt); // be careful here
     }
     
     return 0;
 }
 
-
 static void init_empty_link_table() {
     int i;
 
@@ -958,7 +926,6 @@ static int addto_routing_link_tables(struct routing_entry *route_tab,
        new_route = NULL;       
     }
 
-
     return 0;
 }
 
@@ -977,11 +944,12 @@ static int handle_init_tables_hcall(struct guest_info * info, uint_t hcall_id, v
     struct link_entry *link_array;
     struct routing_entry *route_array;   
 
+    PrintDebug("Vnet: In handle_init_tables_hcall\n");
+
     if (guest_va_to_host_va(info, guest_addr, &info_addr) == -1) {
        PrintError("VNET: Could not translate guest address\n");
        return -1;
     }
-
     init_info = (struct table_init_info *)info_addr;
 
     if (guest_va_to_host_va(info, init_info->routing_table_start, &route_addr) == -1) {
@@ -1001,7 +969,6 @@ static int handle_init_tables_hcall(struct guest_info * info, uint_t hcall_id, v
     return 0;
 }
 
-
 void v3_vnet_init(struct guest_info * vm) {
     init_tables();
     init_pkt_queue();