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.


vnet cleanup
Jack Lange [Sun, 21 Feb 2010 20:22:01 +0000 (14:22 -0600)]
palacios/include/palacios/vmm_dev_mgr.h
palacios/include/palacios/vmm_vnet.h
palacios/src/devices/lnx_virtio_nic.c
palacios/src/devices/lnx_virtio_vnet.c
palacios/src/devices/vnet_nic.c
palacios/src/palacios/vmm_vnet.c

index 84fd53c..23b861d 100644 (file)
@@ -159,12 +159,11 @@ 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 (*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);
+
+    // This will be filled in by the frontend when a backend is connected.
+    // The backend then calls this function for packet RX
+    int (*recv)(uint8_t * buf, uint32_t count, void * private_data);
+    void * frontend_data;
 };
 
 struct v3_dev_console_ops {
@@ -179,6 +178,7 @@ int v3_dev_add_blk_frontend(struct v3_vm_info * vm,
                                            v3_cfg_tree_t * cfg, 
                                            void * private_data), 
                            void * priv_data);
+
 int v3_dev_connect_blk(struct v3_vm_info * vm, 
                       char * frontend_name, 
                       struct v3_dev_blk_ops * ops, 
index 1a88c24..5a6e4fd 100644 (file)
 #ifndef __VNET_H__
 #define __VNET_H__
 
+#ifdef __V3VEE__
+
 #include <palacios/vmm.h>
-#include <palacios/vmm_string.h>
-#include <palacios/vmm_types.h>
-#include <palacios/vmm_queue.h>
-#include <palacios/vmm_hashtable.h>
-#include <palacios/vmm_sprintf.h>
 
 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
 
+
+#define VNET_HASH_SIZE 16
+#define ETHERNET_HEADER_LEN 14
+#define ETHERNET_DATA_MAX   1500
+#define ETHERNET_PACKET_LEN (ETHERNET_HEADER_LEN + ETHERNET_DATA_MAX)
+
 //routing table entry
 struct v3_vnet_route {
-    char src_mac[6];
-    char dest_mac[6];
+    uint8_t src_mac[6];
+    uint8_t dst_mac[6];
 
-    mac_type_t src_mac_qual;
-    mac_type_t dest_mac_qual;
+    uint8_t src_mac_qual;
+    uint8_t dst_mac_qual;
 
-    int link_idx; //link[dest] is the link to be used to send pkt
-    link_type_t link_type; //EDGE|INTERFACE|ANY
+    uint32_t dst_id; //link[dest] is the link to be used to send pkt
+    uint8_t dst_type; //EDGE|INTERFACE|ANY
  
-    int src_link_idx;
-    link_type_t src_type; //EDGE|INTERFACE|ANY
-};
+    uint32_t src_id;
+    uint8_t src_type; //EDGE|INTERFACE|ANY
+} __attribute__((packed));
 
 
-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);
+struct v3_vnet_pkt {
+    uint32_t size; 
+    
+    uint8_t dst_type;
+    uint32_t dst_id;
 
-int v3_vnet_add_route(struct v3_vnet_route *route);
+    /*
+     * IMPORTANT The next three fields must be grouped and packed together
+     *  They are used to generate a hash value 
+     */
+    union {
+       uint8_t hash_buf[VNET_HASH_SIZE];
+       struct {
+           uint8_t src_type;
+           uint32_t src_id;
+           uint8_t data[ETHERNET_PACKET_LEN];
+       } __attribute__((packed));
+    } __attribute__((packed));
+} __attribute__((packed));
 
-//int v3_vnet_del_route();
-//int v3_vnet_get_routes();
 
+int v3_vnet_send_pkt(struct v3_vnet_pkt * pkt);
 
-//int v3_vnet_add_link(struct v3_vnet_link link);
+int v3_vnet_add_route(struct v3_vnet_route route);
+
+//int v3_vnet_del_route();
 
-// int v3_vnet_del_link();
-//int v3_vnet_get_link(int idx, struct vnet_link * link);
 
 
-int v3_init_vnet();
+int V3_init_vnet();
 
 //int v3_vnet_add_bridge(struct v3_vm_info * vm, uint8_t mac[6]);
 
-int v3_vnet_add_node(struct v3_vm_info *info, 
-                  char * dev_name, 
-                  uchar_t mac[6], 
-                   int (*netif_input)(struct v3_vm_info * vm, uchar_t * pkt, uint_t size, void * private_data), 
+int v3_vnet_add_dev(struct v3_vm_info *info, char * dev_name, uint8_t mac[6], 
+                   int (*dev_input)(struct v3_vm_info * vm, struct v3_vnet_pkt * pkt, void * private_data), 
                    void * priv_data);
 
 
@@ -80,4 +95,6 @@ int v3_vnet_pkt_process();
 
 #endif
 
+#endif
+
 
index 69e8293..26b32f6 100644 (file)
@@ -171,104 +171,8 @@ static int copy_data_to_desc(struct virtio_net_state * virtio_state, struct vrin
     return len;
 }
 
-//send data to guest
-int send_pkt_to_guest(struct virtio_net_state * virtio, uchar_t * buf, uint_t size, int raw, void * private_data) 
-{
-    struct virtio_queue * q = &(virtio->rx_vq);
-    struct virtio_net_hdr hdr;
-    uint32_t hdr_len = sizeof(struct virtio_net_hdr);
-    uint32_t data_len = size;
-    uint32_t offset = 0;
-       
-    PrintDebug("VIRTIO NIC:  sending packet to virtio nic %p, size:%d", virtio, size);
-
-    virtio->pkt_recv ++;
-    if (!raw) {
-       data_len -= hdr_len;
-    }
-
-    build_receive_header(&hdr, buf, 1);
-
-    if (q->ring_avail_addr == 0) {
-       PrintError("Queue is not set\n");
-       return -1;
-    }
-
-    if (q->last_avail_idx > q->avail->index)
-       q->idx_overflow = true;
-    q->last_avail_idx = q->avail->index;
-
-    if (q->cur_avail_idx < q->avail->index || (q->idx_overflow && q->cur_avail_idx < q->avail->index+65536)){
-       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;
-
-       hdr_desc = &(q->desc[hdr_idx]);
-       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");
-           return -1;
-       }
-
-       memcpy((void *)hdr_addr, &hdr, sizeof(struct virtio_net_hdr));
-       if (offset >= data_len) {
-           hdr_desc->flags &= ~VIRTIO_NEXT_FLAG;
-       }
-
-       for (buf_idx = hdr_desc->next; offset < data_len; buf_idx = q->desc[hdr_idx].next) {
-           struct vring_desc * buf_desc = &(q->desc[buf_idx]);
-           uint32_t len = 0;
-
-           len = copy_data_to_desc(virtio, buf_desc, buf + offset, data_len - offset);     
-           offset += len;
-           if (offset < data_len) {
-               buf_desc->flags = VIRTIO_NEXT_FLAG;             
-           }
-           buf_desc->length = len;
-       }
-       
-       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 = data_len + hdr_len; // This should be the total length of data sent to guest (header+pkt_data)
-       q->used->index++;
-
-       int last_idx = q->cur_avail_idx;
-       q->cur_avail_idx++;
-       if (q->cur_avail_idx < last_idx)
-           q->idx_overflow = false;
-    } else {
-       virtio->pkt_drop++;
-
-#ifdef VIRTIO_NIC_PROFILE
-       PrintError("Virtio NIC: %p, one pkt dropped receieved: %ld, dropped: %ld, sent: %ld curidx: %d, avaiIdx: %d\n", 
-               virtio, virtio->pkt_recv, virtio->pkt_drop, virtio->pkt_sent, q->cur_avail_idx, q->avail->index);
-#endif
-    }
 
-    if (!(q->avail->flags & VIRTIO_NO_IRQ_FLAG)) {
-       PrintDebug("Raising IRQ %d\n",  virtio->pci_dev->config_header.intr_line);
-       v3_pci_raise_irq(virtio->virtio_dev->pci_bus, 0, virtio->pci_dev);
-       virtio->virtio_cfg.pci_isr = 0x1;
-    }
 
-#ifdef VIRTIO_NIC_PROFILE
-    if ((virtio->pkt_recv % 10000) == 0){
-       PrintError("Virtio NIC: %p, receieved: %ld, dropped: %ld, sent: %ld\n", 
-               virtio, virtio->pkt_recv, virtio->pkt_drop, virtio->pkt_sent);
-    }
-#endif
-
-    
-    return offset;
-}
-
-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 send_pkt_to_guest(virtio_state, buf, size, 1, NULL);
-}
 
 static int get_desc_count(struct virtio_queue * q, int index) {
     struct vring_desc * tmp_desc = &(q->desc[index]);
@@ -291,12 +195,14 @@ static int handle_pkt_tx(struct virtio_net_state * virtio_state)
     struct virtio_queue * q = &(virtio_state->tx_vq);
     struct virtio_net_hdr * hdr = NULL;
 
-    if (q->avail->index < q->last_avail_idx)
+    if (q->avail->index < q->last_avail_idx) {
        q->idx_overflow = true;
+    }
+
     q->last_avail_idx = q->avail->index;
 
     while (q->cur_avail_idx < q->avail->index || 
-                (q->idx_overflow && q->cur_avail_idx < (q->avail->index + 65536))) {
+          (q->idx_overflow && q->cur_avail_idx < (q->avail->index + 65536))) {
        struct vring_desc * hdr_desc = NULL;
        addr_t hdr_addr = 0;
        uint16_t desc_idx = q->avail->ring[q->cur_avail_idx % q->queue_size];
@@ -330,9 +236,12 @@ static int handle_pkt_tx(struct virtio_net_state * virtio_state)
        q->used->index++;
 
        int last_idx = q->cur_avail_idx;
+
        q->cur_avail_idx ++;
-       if (q->cur_avail_idx < last_idx)
+
+       if (q->cur_avail_idx < last_idx) {
            q->idx_overflow = false;
+       }
     }
 
     if (!(q->avail->flags & VIRTIO_NO_IRQ_FLAG)) {
@@ -558,6 +467,98 @@ static int virtio_io_read(struct guest_info *core, uint16_t port, void * dst, ui
 }
 
 
+
+
+static int virtio_rx(uint8_t * buf, uint32_t size, void * private_data) {
+    struct virtio_net_state * virtio = (struct virtio_net_state *)private_data;
+    struct virtio_queue * q = &(virtio->rx_vq);
+    struct virtio_net_hdr hdr;
+    uint32_t hdr_len = sizeof(struct virtio_net_hdr);
+    uint32_t data_len = size;
+    uint32_t offset = 0;
+       
+    PrintDebug("VIRTIO NIC:  sending packet to virtio nic %p, size:%d", virtio, size);
+
+    virtio->pkt_recv ++;
+
+    data_len -= hdr_len;
+
+
+    build_receive_header(&hdr, buf, 1);
+
+    if (q->ring_avail_addr == 0) {
+       PrintError("Queue is not set\n");
+       return -1;
+    }
+
+    if (q->last_avail_idx > q->avail->index)
+       q->idx_overflow = true;
+    q->last_avail_idx = q->avail->index;
+
+    if (q->cur_avail_idx < q->avail->index || (q->idx_overflow && q->cur_avail_idx < q->avail->index+65536)){
+       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;
+
+       hdr_desc = &(q->desc[hdr_idx]);
+       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");
+           return -1;
+       }
+
+       memcpy((void *)hdr_addr, &hdr, sizeof(struct virtio_net_hdr));
+       if (offset >= data_len) {
+           hdr_desc->flags &= ~VIRTIO_NEXT_FLAG;
+       }
+
+       for (buf_idx = hdr_desc->next; offset < data_len; buf_idx = q->desc[hdr_idx].next) {
+           struct vring_desc * buf_desc = &(q->desc[buf_idx]);
+           uint32_t len = 0;
+
+           len = copy_data_to_desc(virtio, buf_desc, buf + offset, data_len - offset);     
+           offset += len;
+           if (offset < data_len) {
+               buf_desc->flags = VIRTIO_NEXT_FLAG;             
+           }
+           buf_desc->length = len;
+       }
+       
+       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 = data_len + hdr_len; // This should be the total length of data sent to guest (header+pkt_data)
+       q->used->index++;
+
+       int last_idx = q->cur_avail_idx;
+       q->cur_avail_idx++;
+       if (q->cur_avail_idx < last_idx)
+           q->idx_overflow = false;
+    } else {
+       virtio->pkt_drop++;
+
+#ifdef VIRTIO_NIC_PROFILE
+       PrintError("Virtio NIC: %p, one pkt dropped receieved: %ld, dropped: %ld, sent: %ld curidx: %d, avaiIdx: %d\n", 
+               virtio, virtio->pkt_recv, virtio->pkt_drop, virtio->pkt_sent, q->cur_avail_idx, q->avail->index);
+#endif
+    }
+
+    if (!(q->avail->flags & VIRTIO_NO_IRQ_FLAG)) {
+       PrintDebug("Raising IRQ %d\n",  virtio->pci_dev->config_header.intr_line);
+       v3_pci_raise_irq(virtio->virtio_dev->pci_bus, 0, virtio->pci_dev);
+       virtio->virtio_cfg.pci_isr = 0x1;
+    }
+
+#ifdef VIRTIO_NIC_PROFILE
+    if ((virtio->pkt_recv % 10000) == 0){
+       PrintError("Virtio NIC: %p, receieved: %ld, dropped: %ld, sent: %ld\n", 
+               virtio, virtio->pkt_recv, virtio->pkt_drop, virtio->pkt_sent);
+    }
+#endif
+
+    
+    return offset;
+}
+
+
 static struct v3_device_ops dev_ops = {
     .free = virtio_free,
     .reset = NULL,
@@ -648,8 +649,8 @@ 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);
+    ops->recv = virtio_rx;
+    ops->frontend_data = net_state;
 
     return 0;
 }
index 65eed65..ccd2620 100644 (file)
@@ -155,7 +155,7 @@ static int handle_cmd_kick(struct guest_info * core, struct virtio_vnet_state *
                // add route
                PrintDebug("Adding VNET Route\n");
 
-               tmp_status = v3_vnet_add_route(route);
+               tmp_status = v3_vnet_add_route(*route);
 
                PrintDebug("VNET Route Added\n");
 
index 2b40c50..ee269c5 100644 (file)
 #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;
+    struct guest_info * core;
        
     void *frontend_data;
     int (*frontend_input)(struct v3_vm_info *info, 
-                                   uchar_t * buf,
-                                 uint32_t size,
-                                 void *private_data);
+                         uchar_t * buf,
+                         uint32_t size,
+                         void *private_data);
 };
 
 //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){
     PrintDebug("Virito NIC: In vnet_send: guest net state %p\n", private_data);
+    struct v3_vnet_pkt * pkt = NULL; 
 
-    v3_vnet_send_rawpkt(buf, len, private_data);
-    return 0;
-}
-
-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;
+    // fill in packet
 
+    v3_vnet_send_pkt(pkt);
     return 0;
 }
 
 
+// We need to make this dynamically allocated
 static struct v3_dev_net_ops net_ops = {
     .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;
+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;
        
-    PrintDebug("Vnet-nic: In input: vnet_nic state %p\n", vnetnic);    
+    // PrintDebug("Vnet-nic: In input: vnet_nic state %p\n", vnetnic); 
 
-    return vnetnic->frontend_input(info, buf, len, vnetnic->frontend_data);
+    return net_ops.recv(pkt->data, pkt->size, net_ops.frontend_data);
 }
 
 #if 0
@@ -157,40 +140,16 @@ int v3_vnetnic_pktprocess(struct guest_info * info)
 #endif
 
 //register a virtio device to the vnet as backend
-int register_to_vnet(struct v3_vm_info *info,
-                                               struct vnet_nic_state *vnet_nic,
-                                               char *dev_name,
-                                               uchar_t mac[6]){
-    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;
-
+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);
        
-    int idx = v3_vnet_add_node(info, dev_name, mac, virtio_input, (void *)vnet_nic);
-
-    if (idx < 0) return -1;
-
- //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;
-    route.link_idx = idx;
-    route.link_type = LINK_EDGE;
-    route.src_link_idx = -1;
-    route.src_type = LINK_ANY;
-    v3_vnet_add_route(&route);
-
-    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);
+    v3_vnet_add_dev(vm, dev_name, mac, virtio_input, (void *)vnet_nic);
+
+
 
     return 0;
 }
@@ -229,10 +188,9 @@ static int vnet_nic_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
        return -1;
     }
 
-    vnetnic->inpkt_q = v3_create_queue();
-
-    if(register_to_vnet(vm, vnetnic, name, vnetnic->mac) == -1)
-      return -1;
+    if (register_to_vnet(vm, vnetnic, name, vnetnic->mac) == -1) {
+       return -1;
+    }
 
     PrintDebug("Vnet-nic device %s initialized\n", name);
 
index ecaa963..46be678 100644 (file)
@@ -20,9 +20,9 @@
  */
  
 #include <palacios/vmm_vnet.h>
-#include <palacios/vmm_hypercall.h>
 #include <palacios/vm_guest_mem.h>
 #include <palacios/vmm_lock.h>
+#include <palacios/vmm_queue.h>
 
 #ifndef CONFIG_DEBUG_VNET
 #undef PrintDebug
 #endif
 
 
-#define ETHERNET_HEADER_LEN 14
-#define ETHERNET_DATA_MIN   46
-#define ETHERNET_DATA_MAX   1500
-#define ETHERNET_PACKET_LEN (ETHERNET_HEADER_LEN + ETHERNET_DATA_MAX)
 
 
-typedef enum {TCP_TYPE, UDP_TYPE, NONE_TYPE} prot_type_t;
 
-#define VNET_INITAB_HCALL 0xca00
 
-struct eth_header {
-    uchar_t dest[6];
-    uchar_t src[6];
+struct eth_hdr {
+    uint8_t dst_mac[6];
+    uint8_t src_mac[6];
     uint16_t type; // indicates layer 3 protocol 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));
-
-
-struct ethernet_pkt {
-    uint32_t size; //size of data field
-    uint16_t type;
-    uint8_t use_header;
-    struct udp_link_header ext_hdr;
-    char data[ETHERNET_PACKET_LEN];
-}__attribute__((packed));
+} __attribute__((packed));
+
+
 
 
 #define DEVICE_NAME_LEN 20
-struct vnet_if_device {
+struct vnet_dev {
     char name[DEVICE_NAME_LEN];
-    uchar_t mac_addr[6];
-    struct v3_vm_info *vm;
+    uint8_t mac_addr[6];
+    struct v3_vm_info * vm;
     
-    int (*input)(struct v3_vm_info *vm, uchar_t *data, uint32_t len, void *private_data);
+    int (*input)(struct v3_vm_info * vm, struct v3_vnet_pkt * pkt,  void * private_data);
+    void * private_data;
     
-    void *private_data;
-}__attribute__((packed));
-
-struct vnet_if_link {
-    prot_type_t pro_type; //transport layer protocal type of this link
-    unsigned long dest_ip;
-    uint16_t dest_port;
-
-    struct udp_link_header vnet_header; //header applied to the packet in/out from this link
+    int dev_id;
+    struct list_head node;
+} __attribute__((packed));
 
-    int (*input)(uchar_t *data, uint32_t len, void *private_data);
-    
-    void *private_data;
-}__attribute__((packed));
 
 
-struct link_entry {
-    link_type_t type;
-  
-    union {
-       struct vnet_if_device *dst_dev;
-       struct vnet_if_link *dst_link;
-    } __attribute__((packed));
 
-    int use;
-}__attribute__((packed));
 
-//routing table entry
-struct routing_entry {
-    char src_mac[6];
-    char dest_mac[6];
+struct vnet_route_info {
+    struct v3_vnet_route route_def;
 
-    mac_type_t src_mac_qual;
-    mac_type_t dest_mac_qual;
+    struct vnet_dev * dst_dev;
+    struct vnet_dev * src_dev;
 
-    int link_idx; //link[dest] is the link to be used to send pkt
-    link_type_t link_type; //EDGE|INTERFACE|ANY
-    int src_link_idx;
-    link_type_t src_type; //EDGE|INTERFACE|ANY
+    struct list_head node;
+    struct list_head match_node; // used for route matching
 };
 
 
-// 14 (ethernet frame) + 20 bytes
-struct in_pkt_header {
-    uchar_t ethernetdest[6];
-    uchar_t ethernetsrc[6];
-    uchar_t ethernettype[2]; //layer 3 protocol type
-    char ip[20];
-}__attribute__((packed));
 
 
-#define MAX_LINKS 10
-#define MAX_ROUTES 10
-#define HASH_KEY_LEN 16
-#define MIN_CACHE_SIZE 100
-#define HASH_KEY_SIZE 16
+struct route_list {
+    uint8_t hash_buf[VNET_HASH_SIZE];
 
-struct link_table {
-    struct link_entry * links[MAX_LINKS];
-    uint16_t size;
-    v3_lock_t lock;
-}__attribute__((packed));
+    uint32_t num_routes;
+    struct vnet_route_info * routes[0];
+} __attribute__((packed));
 
-struct routing_table {
-    struct routing_entry * routes[MAX_ROUTES];
-    uint16_t size;
-    v3_lock_t lock;
-}__attribute__((packed));
 
-typedef char * route_hashkey_t;
 
-struct route_cache_entry {
-    int num_matched_routes;
-    int * matches; 
-};
+static struct {
+    struct list_head routes;
+    struct list_head devs;
 
-struct vnet_state_t {
-    struct link_table g_links;
-    struct routing_table g_routes;
-    struct gen_queue * g_inpkt_q;
-    struct hashtable * g_route_cache;
-    v3_lock_t cache_lock;
-};
+    int num_routes;
+    int num_devs;
 
-static struct vnet_state_t g_vnet_state;//global state for vnet
+    v3_lock_t lock;
 
-static uint16_t ip_xsum(struct ip_header *ip_hdr, int hdr_len){
-    long sum = 0;
+    struct gen_queue * inpkt_q;
+    struct hashtable * route_cache;
 
-    uint16_t *p = (uint16_t*) ip_hdr;
-    while(hdr_len > 1){
-        sum += *(p++);
-        if(sum & 0x80000000)
-            sum = (sum & 0xFFFF) + (sum >> 16);
-            hdr_len -= 2;
-        }
-    if(hdr_len) 
-        sum += (uint16_t) *(uchar_t *)p;
-          
-    while(sum>>16)
-        sum = (sum & 0xFFFF) + (sum >> 16);
+} vnet_state;
 
-    return (uint16_t)~sum;
-}
 
-static void ethernet_packet_init(struct ethernet_pkt *pt, 
-                                                              uchar_t *data, 
-                                                              const size_t size) {
-    pt->size = size;
-    pt->use_header = 0;
-    memset(&pt->ext_hdr, 0, sizeof(struct udp_link_header));
-    memcpy(pt->data, data, size);
-}
 
-static inline uint_t hash_from_key_fn(addr_t hashkey) {    
-    return v3_hash_buffer((uint8_t *)hashkey, HASH_KEY_LEN);
-}
 
-static inline int hash_key_equal(addr_t key1, addr_t key2) {
-    return (memcmp((uint8_t *)key1, (uint8_t *)key2, HASH_KEY_LEN) == 0);
+/* 
+ * A VNET packet is a packed struct with the hashed fields grouped together.
+ * This means we can generate the hash from an offset into the pkt struct
+ */
+static inline uint_t hash_fn(addr_t hdr_ptr) {    
+    uint8_t * hdr_buf = (uint8_t *)&(hdr_ptr);
+    
+    return v3_hash_buffer(hdr_buf, VNET_HASH_SIZE);
 }
 
-static int init_route_cache(struct vnet_state_t *vnet_state) { 
-    vnet_state->g_route_cache = v3_create_htable(MIN_CACHE_SIZE, 
-                                                                      &hash_from_key_fn, 
-                                                                      &hash_key_equal);
-
-    if (vnet_state->g_route_cache == NULL) {
-        PrintError("Vnet: Route Cache Init Fails\n");
-        return -1;
-    }
-
-    return 0;
+static inline int hash_eq(addr_t key1, addr_t key2) {
+    return (memcmp((uint8_t *)key1, (uint8_t *)key2, VNET_HASH_SIZE) == 0);
 }
 
-static void make_hash_key(route_hashkey_t hashkey,
-                                               char src_addr[6],
-                                               char dest_addr[6],
-                                               char src_type,
-                                               int src_index) {
-    int j;
 
-    for (j = 0; j < 6; j++) {
-       hashkey[j] = src_addr[j];
-       hashkey[j + 6] = dest_addr[j] + 1;
-    }
-
-    hashkey[12] = src_type;
+static int add_route_to_cache(struct v3_vnet_pkt * pkt, struct route_list * routes) {
+    memcpy(routes->hash_buf, pkt->hash_buf, VNET_HASH_SIZE);    
 
-    *(int *)(hashkey + 12) = src_index;
-}
-
-static int add_route_to_cache(route_hashkey_t hashkey, 
-                                                       int num_matched_r, 
-                                                       int * matches) {
-    struct route_cache_entry * new_entry = NULL;
-    struct vnet_state_t *vnet_state = &g_vnet_state;
-    int i;
-    
-    new_entry = (struct route_cache_entry *)V3_Malloc(sizeof(struct route_cache_entry));
-    if (new_entry == NULL) {
-       PrintError("Vnet: Malloc fails\n");
-       return -1;
-    }
-    
-    new_entry->num_matched_routes = num_matched_r;
-    new_entry->matches = (int *)V3_Malloc(num_matched_r * sizeof(int));
-    
-    if (new_entry->matches == NULL) {
-       PrintError("Vnet: Malloc fails\n");
-       return -1;
-    }
-    
-    for (i = 0; i < num_matched_r; i++) {
-       new_entry->matches[i] = matches[i];
-    }
-    
-    if (v3_htable_insert(vnet_state->g_route_cache, (addr_t)hashkey, (addr_t)new_entry) == 0) {
+    if (v3_htable_insert(vnet_state.route_cache, (addr_t)routes->hash_buf, (addr_t)routes) == 0) {
        PrintError("Vnet: Failed to insert new route entry to the cache\n");
-       V3_Free(new_entry->matches);
-       V3_Free(new_entry);
+       return -1;
     }
     
     return 0;
 }
 
 static int clear_hash_cache() {
-    struct vnet_state_t *vnet_state = &g_vnet_state;
 
-    v3_free_htable(vnet_state->g_route_cache, 1, 1);           
-    vnet_state->g_route_cache = v3_create_htable(MIN_CACHE_SIZE, 
-                                                                        hash_from_key_fn, 
-                                                                        hash_key_equal);
-    
-    if (vnet_state->g_route_cache == NULL) {
-        PrintError("Vnet: Route Cache Create Failurely\n");
-        return -1;
-    }
+    /* USE the hash table iterators. 
+     * See v3_swap_flush(struct v3_vm_info * vm) in vmm_shdw_pg_swapbypass.c
+     */
 
     return 0;
 }
 
-static int look_into_cache(route_hashkey_t hashkey, int * matches) {
-    struct route_cache_entry * found = NULL;
-    int n_matches = -1;
-    int i = 0;
-    struct vnet_state_t *vnet_state = &g_vnet_state;
+static int look_into_cache(struct v3_vnet_pkt * pkt, struct route_list ** routes) {
     
-    found = (struct route_cache_entry *)v3_htable_search(vnet_state->g_route_cache, 
-                                                                               (addr_t)hashkey);
+    *routes = (struct route_list *)v3_htable_search(vnet_state.route_cache, (addr_t)pkt);
    
-    if (found != NULL) {
-        n_matches = found->num_matched_routes;
-
-        for (i = 0; i < n_matches; i++) {
-            matches[i] = found->matches[i];
-       }
-    }
-
-    return n_matches;
+    return 0;
 }
 
 
-#ifdef CONFIG_DEBUG_VNET
 
-static void print_packet(uchar_t *pkt, int size) {
-    PrintDebug("Vnet: 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);
 
-    if (isdigit(x)) {
-       return x - '0';
-    } else {
-       return 10 + (x - 'A');
-    }
-}
 
-static inline uint8_t hex_byte_to_byte(const uint8_t hexbyte[2]) {
-    return ((hex_nybble_to_nybble(hexbyte[0]) << 4) + 
-           (hex_nybble_to_nybble(hexbyte[1]) & 0xf));
-}
-
-static inline void string_to_mac(const char *str, uint8_t mac[6]) {
-    int k;
+int v3_vnet_add_route(struct v3_vnet_route route) {
+    struct vnet_route_info * new_route = NULL;
+    unsigned long flags; 
 
-    for (k = 0; k < 6; k++) {
-       mac[k] = hex_byte_to_byte(&(str[(2 * k) + k]));
-    }
-}
+    new_route = (struct vnet_route_info *)V3_Malloc(sizeof(struct vnet_route_info));
+    memset(new_route, 0, sizeof(struct vnet_route_info));
 
-static inline void mac_to_string(char mac[6], char * buf) {
-    snprintf(buf, 20, "%02x:%02x:%02x:%02x:%02x:%02x", 
-            mac[0], mac[1], mac[2],
-            mac[3], mac[4], mac[5]);
-}
+    PrintDebug("Vnet: vnet_add_route_entry\n");        
+    
+    new_route->route_def = route;
 
+    /* TODO: Find devices */
+    if (new_route->route_def.dst_type == LINK_INTERFACE) {
+       // new_route->dst_dev = FIND_DEV();
+    }
 
-static void print_route(struct routing_entry *route){
-    char dest_str[18];
-    char src_str[18];
+    if (new_route->route_def.src_type == LINK_INTERFACE) {
+       // new_route->src_dev = FIND_DEV()
+    }
 
-    mac_to_string(route->src_mac, src_str);  
-    mac_to_string(route->dest_mac, dest_str);
+    flags = v3_lock_irqsave(vnet_state.lock);
+    list_add(&(new_route->node), &(vnet_state.routes));
+    v3_unlock_irqrestore(vnet_state.lock, flags);
+   
+    clear_hash_cache();
 
-    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);
+    return 0;
 }
-       
 
-static void dump_routes(struct routing_entry **route_tables) {
-    int i;
 
-    PrintDebug("\nVnet: route table dump start =====\n");
 
-    for(i = 0; i < MAX_ROUTES; i++) {
-        if (route_tables[i] != NULL){
-            print_route(route_tables[i]);
-        }
-    }
-
-    PrintDebug("\nVnet: route table dump end =====\n");
-}
-
-#endif
+// 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) {
+    struct vnet_route_info * route = NULL; 
+    struct route_list * matches = NULL;
+    int num_matches = 0;
+    int max_rank = 0;
+    struct list_head match_list;
+    struct eth_hdr * hdr = (struct eth_hdr *)(pkt->data);
+    uint8_t src_type = pkt->src_type;
+    uint32_t src_link = pkt->src_id;
 
-static int __add_link_entry(struct link_entry * link) {
-    int idx;
-    struct vnet_state_t *vnet_state = &g_vnet_state;
+#ifdef CONFIG_DEBUG_VNET
+    {
+       char dst_str[18];
+       char src_str[18];
 
-    v3_lock(vnet_state->g_links.lock);
-    for (idx = 0; idx < MAX_LINKS; idx++) {
-       if (vnet_state->g_links.links[idx] == NULL) {
-           vnet_state->g_links.links[idx] = link;
-           vnet_state->g_links.size++;
-           break;
-       }
+       mac_to_string(hdr->src_mac, src_str);  
+       mac_to_string(hdr->dst_mac, dest_str);
+       PrintDebug("Vnet: match_route. pkt: SRC(%s), DEST(%s)\n", src_str, dest_str);
     }
-    v3_unlock(vnet_state->g_links.lock);
+#endif
 
-    if (idx == MAX_LINKS) {
-       PrintDebug("VNET: No available Link entry for new link\n");
-       return -1;
-    }
+    INIT_LIST_HEAD(&match_list);
+    
+#define UPDATE_MATCHES(rank) do {                              \
+       if (max_rank < (rank)) {                                \
+           max_rank = (rank);                                  \
+           INIT_LIST_HEAD(&match_list);                        \
+                                                               \
+           list_add(&(route->match_node), &match_list);        \
+           num_matches = 1;                                    \
+       } else if (max_rank == (rank)) {                        \
+           list_add(&(route->match_node), &match_list);        \
+           num_matches++;                                      \
+       }                                                       \
+    } while (0)
+    
 
-    return idx;
-}
 
-static int __add_route_entry(struct routing_entry * route) {
-    int idx;
-    struct vnet_state_t *vnet_state = &g_vnet_state;
+    list_for_each_entry(route, &(vnet_state.routes), node) {
+       struct v3_vnet_route * route_def = &(route->route_def);
 
-    v3_lock(vnet_state->g_routes.lock);
-    for (idx = 0; idx < MAX_ROUTES; idx++) {
-       if (vnet_state->g_routes.routes[idx] == NULL) {
-           vnet_state->g_routes.routes[idx] = route;
-           vnet_state->g_routes.size++;
-          break;
+       // CHECK SOURCE TYPE HERE
+       if ( (route_def->src_type != LINK_ANY) && 
+            ( (route_def->src_type != src_type) || 
+              ( (route_def->src_id != src_link) &&
+                (route_def->src_id != (uint32_t)-1)))) {
+           continue;
        }
-    }
-    v3_unlock(vnet_state->g_routes.lock);
-
-    if(idx == MAX_LINKS){
-        PrintDebug("VNET: No available route entry for new route\n");
-        return -1;
-    }
 
-#ifdef CONFIG_DEBUG_VNET
-    dump_routes(vnet_state->g_routes.routes);
-#endif
-
-    return idx;
-}
 
-int v3_vnet_add_route(struct v3_vnet_route *route){
-    struct routing_entry * new_route = (struct routing_entry *)V3_Malloc(sizeof(struct routing_entry));
-    int idx = -1;
-
-    PrintDebug("Vnet: vnet_add_route_entry\n");
+       if ((route_def->dst_mac_qual == MAC_ANY) &&
+           (route_def->src_mac_qual == MAC_ANY)) {      
+           UPDATE_MATCHES(3);
+       }
        
-    memset(new_route, 0, sizeof(struct routing_entry));
-    if ((route->src_mac_qual != MAC_ANY)) {
-        memcpy(new_route->src_mac, route->src_mac, 6);
-    }
+       if (memcmp(route_def->src_mac, hdr->src_mac, 6) == 0) {
+           if (route_def->src_mac_qual != MAC_NOT) {
+               if (route_def->dst_mac_qual == MAC_ANY) {
+                   UPDATE_MATCHES(6);
+               } else if (route_def->dst_mac_qual != MAC_NOT &&
+                          memcmp(route_def->dst_mac, hdr->dst_mac, 6) == 0) {
+                   UPDATE_MATCHES(8);
+               }
+           }
+       }
            
-    if ((route->dest_mac_qual != MAC_ANY)) {
-        memcpy(new_route->dest_mac, route->dest_mac, 6);
-    }
+       if (memcmp(route_def->dst_mac, hdr->dst_mac, 6) == 0) {
+           if (route_def->dst_mac_qual != MAC_NOT) {
+               if (route_def->src_mac_qual == MAC_ANY) {
+                   UPDATE_MATCHES(6);
+               } else if ((route_def->src_mac_qual != MAC_NOT) && 
+                          (memcmp(route_def->src_mac, hdr->src_mac, 6) == 0)) {
+                   UPDATE_MATCHES(8);
+               }
+           }
+       }
            
-    new_route->src_mac_qual = route->src_mac_qual;
-    new_route->dest_mac_qual = route->dest_mac_qual;
-    new_route->link_idx= route->link_idx;
-    new_route->link_type = route->link_type;
-    new_route->src_link_idx = route->src_link_idx;
-    new_route->src_type = route->src_type;
-
-    if ((idx = __add_route_entry(new_route)) == -1) {
-       PrintError("Could not add route entry\n");
-        return -1;
+       if ((route_def->dst_mac_qual == MAC_NOT) &&
+           (memcmp(route_def->dst_mac, hdr->dst_mac, 6) != 0)) {
+           if (route_def->src_mac_qual == MAC_ANY) {
+               UPDATE_MATCHES(5);
+           } else if ((route_def->src_mac_qual != MAC_NOT) && 
+                      (memcmp(route_def->src_mac, hdr->src_mac, 6) == 0)) {     
+               UPDATE_MATCHES(7);
+           }
+       }
+       
+       if ((route_def->src_mac_qual == MAC_NOT) &&
+           (memcmp(route_def->src_mac, hdr->src_mac, 6) != 0)) {
+           if (route_def->dst_mac_qual == MAC_ANY) {
+               UPDATE_MATCHES(5);
+           } else if ((route_def->dst_mac_qual != MAC_NOT) &&
+                      (memcmp(route_def->dst_mac, hdr->dst_mac, 6) == 0)) {
+               UPDATE_MATCHES(7);
+           }
+       }
+       
+       // Default route
+       if ( (memcmp(route_def->src_mac, hdr->src_mac, 6) == 0) &
+            (route_def->dst_mac_qual == MAC_NONE)) {
+           UPDATE_MATCHES(4);
+       }
     }
-    
-    clear_hash_cache();
 
-    return idx;
-}
-
-static int match_route(uint8_t * src_mac, 
-                      uint8_t * dst_mac, 
-                      link_type_t src_type, 
-                      int src_index, 
-                      int * matches) {
-    struct routing_entry *route = NULL; 
-    struct vnet_state_t *vnet_state = &g_vnet_state;
-    int matched_routes[MAX_ROUTES];
-    int num_matches = 0;
-    int i;
+    PrintDebug("Vnet: match_route: Matches=%d\n", num_matches);
 
-#ifdef CONFIG_DEBUG_VNET
-    char dest_str[18];
-    char src_str[18];
+    if (num_matches == 0) {
+       return NULL;
+    }
 
-    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);
-#endif
+    matches = V3_Malloc(sizeof(struct route_list) + 
+                       (sizeof(struct vnet_route_info *) * num_matches));
 
-    for(i = 0; i < MAX_ROUTES; i++) {
-        if (vnet_state->g_routes.routes[i] != NULL){
-            route = vnet_state->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 (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++;
-                        }
-                    }
-                }
-
-                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
+    matches->num_routes = num_matches;
 
-    PrintDebug("Vnet: match_route: Matches=%d\n", num_matches);
-       
-    for (i = 0; i < num_matches; i++) {
-        matches[i] = matched_routes[i];
+    {
+       int i = 0;
+       list_for_each_entry(route, &match_list, node) {
+           matches->routes[i++] = route;
+       }
     }
-    
-    return num_matches;
+
+    return matches;
 }
 
-static int handle_one_pkt(struct ethernet_pkt *pkt) {
-    int src_link_index = -1;   //the value of src_link_index of udp always is 0
-    char src_mac[6];
-    char dst_mac[6];
-    int matches[MAX_ROUTES];
-    int num_matched_routes = 0;
-    struct in_pkt_header header;
-    char hash_key[HASH_KEY_SIZE];
-    struct vnet_state_t *vnet_state = &g_vnet_state;
+static int handle_one_pkt(struct v3_vnet_pkt * pkt) {
+    struct route_list * matched_routes = NULL;
     int i;
 
-    // get the ethernet and ip headers from the packet
-    memcpy((void *)&header, (void *)pkt->data, sizeof(header));
-    memcpy(src_mac, header.ethernetsrc, 6);
-    memcpy(dst_mac, header.ethernetdest, 6);
 
 #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);
+    mac_to_string(hdr->src, src_str);  
+    mac_to_string(hdr->dst, dest_str);
     PrintDebug("Vnet: HandleDataOverLink. SRC(%s), DEST(%s)\n", src_str, dest_str);
 #endif
 
-    make_hash_key(hash_key, src_mac, dst_mac, LINK_EDGE, src_link_index); 
-    num_matched_routes = look_into_cache((route_hashkey_t)hash_key, matches);
+    look_into_cache(pkt, &matched_routes);
     
-    if (num_matched_routes == -1) {  
-        num_matched_routes = match_route(src_mac, dst_mac, LINK_ANY, src_link_index, matches); 
-        if (num_matched_routes > 0) {
-            add_route_to_cache(hash_key, num_matched_routes,matches);      
-        }
+    if (matched_routes == NULL) {  
+        matched_routes = match_route(pkt);     
+
+        if (matched_routes) {
+            add_route_to_cache(pkt, matched_routes);      
+       } else {
+           PrintError("Could not find route for packet...\n");
+           return -1;
+       }
     }
     
-    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;
-        int link_index = -1;
-        int pkt_len = 0;
-        struct link_entry * link = NULL;
-
-        route_index = matches[i];
-        link_index = vnet_state->g_routes.routes[route_index]->link_idx;
-
-        if ((link_index < 0) || (link_index > MAX_LINKS) || 
-            (vnet_state->g_links.links[link_index] == NULL)) {
-            continue;
-        }
-       
-        link = vnet_state->g_links.links[link_index];
-        pkt_len = pkt->size;
-        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));
-               
-                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 to link: %d\n", link_index);
-                    continue;
-                }
-            }else {
-                PrintDebug("VNET: Link protocol type not support\n");
-                continue;
-            }
-        } else if (link->type == LINK_INTERFACE) {
-            if ((link->dst_dev->input(link->dst_dev->vm, pkt->data, pkt_len, link->dst_dev->private_data)) != pkt_len) {
-                PrintDebug("VNET: Packet not sent properly to link: %d\n", link_index);
+    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) {
+            if (route->dst_dev->input(route->dst_dev->vm, pkt, route->dst_dev->private_data) == -1) {
+                PrintDebug("VNET: Packet not sent properly\n");
                 continue;
             }
         } else {
-            PrintDebug("Vnet: Wrong Edge type of link: %d\n", link_index);
+            PrintDebug("Vnet: Wrong Edge type\n");
             continue;
         }
 
-        PrintDebug("Vnet: HandleDataOverLink: Forward packet according to Route entry %d to link %d\n", route_index, link_index);
+        PrintDebug("Vnet: HandleDataOverLink: Forward packet according to Route\n");
     }
     
     return 0;
 }
 
-static int send_ethernet_pkt(uchar_t *data, int len, void *private_data) {
-    struct ethernet_pkt *pkt;
-    struct vnet_state_t *vnet_state = &g_vnet_state;
-
-    pkt = (struct ethernet_pkt *)V3_Malloc(sizeof(struct ethernet_pkt));
-    if(pkt == NULL){
-        PrintError("VNET: Memory allocate fails\n");
-        return -1;
-    }
-
-    memset(pkt, 0, sizeof(struct ethernet_pkt));
-    ethernet_packet_init(pkt, data, len);
-    v3_enqueue(vnet_state->g_inpkt_q, (addr_t)pkt);
+int v3_vnet_send_pkt(struct v3_vnet_pkt * pkt) {
+    // find the destination and call the send packet function, passing pkt *
   
 #ifdef CONFIG_DEBUG_VNET
     PrintDebug("VNET: send_pkt: transmitting packet: (size:%d)\n", (int)pkt->size);
-    print_packet((char *)data, len);
+    print_packet(pkt);
 #endif
 
     return 0;
 }
 
-int v3_vnet_send_rawpkt(uchar_t * buf, 
-                                          int len, 
-                                          void *private_data) {
-    PrintDebug("VNET: In v3_vnet_send_rawpkt: pkt length %d\n", len);
+
+/*
+static struct vnet_dev * find_dev_by_id(int idx) {
     
-    return send_ethernet_pkt(buf, len, private_data);
-}
 
-//sending the packet from Dom0, should remove the link header
-int v3_vnet_send_udppkt(uchar_t * buf, 
-                                           int len, 
-                                           void *private_data) {
-    uint_t hdr_len = sizeof(struct udp_link_header);
-       
-    PrintDebug("VNET: In v3_vnet_send_udppkt: pkt length %d\n", len);
-   
-    return send_ethernet_pkt((uchar_t *)(buf+hdr_len), len - hdr_len, private_data);
+    // scan device list
+    return NULL;
 }
+*/
 
-static int search_device(char * device_name) {
-    struct vnet_state_t *vnet_state = &g_vnet_state;
-    int i;
-
-    for (i = 0; i < MAX_LINKS; i++) {
-        if ((vnet_state->g_links.links[i] != NULL) && (vnet_state->g_links.links[i]->type == LINK_INTERFACE)) {
-           if (strcmp(device_name, vnet_state->g_links.links[i]->dst_dev->name) == 0) {
-               return i;
-           }
-        }
-    }
+static struct vnet_dev * find_dev_by_name(char * name) {
 
-    return -1;
+    return NULL;
 }
 
-int v3_vnet_add_node(struct v3_vm_info *info, 
-                  char * dev_name, 
-                  uchar_t mac[6], 
-                   int (*netif_input)(struct v3_vm_info * vm, uchar_t * pkt, uint_t size, void * private_data), 
+int v3_vnet_add_dev(struct v3_vm_info *vm, char * dev_name, 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_if_device * if_dev;
+    struct vnet_dev * new_dev = NULL;
 
-    int idx = search_device(dev_name);
-    if (idx != -1) {
+    new_dev = find_dev_by_name(dev_name);
+
+    if (new_dev) {
        PrintDebug("VNET: register device: Already has device with the name %s\n", dev_name);
        return -1;
     }
     
-    if_dev = (struct vnet_if_device *)V3_Malloc(sizeof(struct vnet_if_device)); 
-    if (if_dev == NULL) {
+    new_dev = (struct vnet_dev *)V3_Malloc(sizeof(struct vnet_dev)); 
+
+    if (new_dev == NULL) {
        PrintError("VNET: Malloc fails\n");
        return -1;
     }
     
-    strcpy(if_dev->name, dev_name);
-    strncpy(if_dev->mac_addr, mac, 6);
-    if_dev->input = netif_input;
-    if_dev->private_data = priv_data;
-    if_dev->vm = info;
-
-    struct link_entry * link = (struct link_entry *)V3_Malloc(sizeof(struct link_entry));
-    link->type = LINK_INTERFACE;
-    link->dst_dev = if_dev;
+    strcpy(new_dev->name, dev_name);
+    memcpy(new_dev->mac_addr, mac, 6);
+    new_dev->input = netif_input;
+    new_dev->private_data = priv_data;
+    new_dev->vm = vm;
 
-    idx = __add_link_entry(link);
+    // ADD TO dev list
+    // increment dev count
 
-    if (idx < 0) return -1;
-
-    return idx;
+    return 0;
 }
 
 int v3_vnet_pkt_process() {
-    struct ethernet_pkt * pkt;
-    struct vnet_state_t *vnet_state = &g_vnet_state;
+    struct v3_vnet_pkt * pkt = NULL;
 
-    while ((pkt = (struct ethernet_pkt *)v3_dequeue(vnet_state->g_inpkt_q))!= NULL) {
+    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, pt type %d\n", (int)pkt->size, (int)pkt->type);  
         } else {
@@ -768,44 +426,83 @@ int v3_vnet_pkt_process() {
     return 0;
 }
 
-static void vnet_state_init(struct vnet_state_t *vnet_state) {
-    int i;
 
-    /*initial links table */
-    for (i = 0; i < MAX_LINKS; i++) {
-        vnet_state->g_links.links[i] = NULL;
-    }
-    vnet_state->g_links.size = 0;
-    if(v3_lock_init(&(vnet_state->g_links.lock)) == -1){
-        PrintError("VNET: Failure to init lock for links table\n");
-    }
+int V3_init_vnet() {
+
     PrintDebug("VNET: Links table initiated\n");
 
-    /*initial routes table */
-    for (i = 0; i < MAX_ROUTES; i++) {
-        vnet_state->g_routes.routes[i] = NULL;
-    }
-    vnet_state->g_routes.size = 0;
-    if(v3_lock_init(&(vnet_state->g_routes.lock)) == -1){
+    INIT_LIST_HEAD(&(vnet_state.routes));
+
+    if (v3_lock_init(&(vnet_state.lock)) == -1){
         PrintError("VNET: Failure to init lock for routes table\n");
     }
+
     PrintDebug("VNET: Routes table initiated\n");
 
     /*initial pkt receiving queue */
-    vnet_state->g_inpkt_q = v3_create_queue();
-    v3_init_queue(vnet_state->g_inpkt_q);
+    vnet_state.inpkt_q = v3_create_queue();
+    v3_init_queue(vnet_state.inpkt_q);
     PrintDebug("VNET: Receiving queue initiated\n");
 
-    /*initial routing cache */
-    init_route_cache(vnet_state);
+    vnet_state.route_cache = v3_create_htable(0, &hash_fn, &hash_eq);
+
+    if (vnet_state.route_cache == NULL) {
+        PrintError("Vnet: Route Cache Init Fails\n");
+        return -1;
+    }
+
+    return 0;
 }
 
 
-int v3_init_vnet() {
-    vnet_state_init(&g_vnet_state);
+
+#ifdef CONFIG_DEBUG_VNET
+
+static void print_packet(struct v3_vnet_pkt * pkt) {
+    PrintDebug("Vnet: data_packet: size: %d\n", pkt->size);
+    v3_hexdump(pkt->data, pkt->size, NULL, 0);
+}
+
+
+static inline void mac_to_string(char mac[6], char * buf) {
+    snprintf(buf, 20, "%02x:%02x:%02x:%02x:%02x:%02x", 
+            mac[0], mac[1], mac[2],
+            mac[3], mac[4], mac[5]);
+}
+
+
+static void print_route(struct routing_entry *route){
+    char dest_str[18];
+    char src_str[18];
+
+    mac_to_string(route->src_mac, src_str);  
+    mac_to_string(route->dest_mac, dest_str);
+
+    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_id, 
+                 route->src_type, 
+                 route->dst_id, 
+                 route->dst_type);
+}
        
-    PrintDebug("VNET Initialized\n");
 
-    return 0;
+static void dump_routes(struct routing_entry **route_tables) {
+    int i;
+
+    PrintDebug("\nVnet: route table dump start =====\n");
+
+    for(i = 0; i < MAX_ROUTES; i++) {
+        if (route_tables[i] != NULL){
+            print_route(route_tables[i]);
+        }
+    }
+
+    PrintDebug("\nVnet: route table dump end =====\n");
 }
 
+#endif