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
[palacios.git] / palacios / src / palacios / vmm_vnet.c
index d68610c..46be678 100644 (file)
@@ -8,24 +8,21 @@
  * http://www.v3vee.org
  *
  * Copyright (c) 2009, Lei Xia <lxia@northwestern.edu> 
- * Copyright (c) 2009, Yuan Tang <ytang@northwestern.edu> 
- * Copyright (c) 2009, Jack Lange <jarusl@cs.northwestern.edu> 
- * Copyright (c) 2009, Peter Dinda <pdinda@northwestern.edu>
+ * Copyright (c) 2009, Yuan Tang <ytang@northwestern.edu>  
  * Copyright (c) 2009, The V3VEE Project <http://www.v3vee.org> 
  * All rights reserved.
  *
  * Author: Lei Xia <lxia@northwestern.edu>
  *        Yuan Tang <ytang@northwestern.edu>
- *        Jack Lange <jarusl@cs.northwestern.edu> 
- *        Peter Dinda <pdinda@northwestern.edu
  *
  * This is free software.  You are permitted to use,
  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
  */
  
 #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
 
 
-struct ethernet_pkt {
-  uint32_t size;
-  uint16_t type;
-  char data[ETHERNET_PACKET_LEN];
-};
 
 
-// 14 (ethernet frame) + 20 bytes
-struct in_pkt_header {
-    char ethernetdest[6];
-    char ethernetsrc[6];
-    unsigned char ethernettype[2]; // indicates layer 3 protocol type
-    char ip[20];
-};
 
-#define VNET_INITAB_HCALL 0xca00  // inital hypercall id
 
-#define MAX_LINKS 10
-#define MAX_ROUTES 10
-#define HASH_KEY_LEN 16
-#define MIN_CACHE_SIZE 100
-static const uint_t hash_key_size = 16;
+struct eth_hdr {
+    uint8_t dst_mac[6];
+    uint8_t src_mac[6];
+    uint16_t type; // indicates layer 3 protocol type
+} __attribute__((packed));
 
-struct link_table {
-    struct link_entry *links[MAX_LINKS];
-    uint16_t size;
-};
 
-struct routing_table {
-    struct routing_entry *routes[MAX_ROUTES];
-    uint16_t size;
-};
 
-static struct link_table g_links;
-static struct routing_table g_routes;
-static struct gen_queue *g_inpkt_q;
 
-/* Hash key format:
- * 0-5:     src_eth_addr
- * 6-11:    dest_eth_addr
- * 12:      src type
- * 13-16:   src index
- */
-typedef char *route_hashkey_t;
+#define DEVICE_NAME_LEN 20
+struct vnet_dev {
+    char name[DEVICE_NAME_LEN];
+    uint8_t mac_addr[6];
+    struct v3_vm_info * vm;
+    
+    int (*input)(struct v3_vm_info * vm, struct v3_vnet_pkt * pkt,  void * private_data);
+    void * private_data;
+    
+    int dev_id;
+    struct list_head node;
+} __attribute__((packed));
+
 
-// This is the hash value, Format: 0: num_matched_routes, 1...n: matches[] -- TY
-struct route_cache_entry {
-    int num_matched_routes;
-    int * matches; 
+
+
+
+struct vnet_route_info {
+    struct v3_vnet_route route_def;
+
+    struct vnet_dev * dst_dev;
+    struct vnet_dev * src_dev;
+
+    struct list_head node;
+    struct list_head match_node; // used for route matching
 };
 
-//the route cache
-static struct hashtable *g_route_cache; 
 
 
-static void print_packet(char *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);
-}
+struct route_list {
+    uint8_t hash_buf[VNET_HASH_SIZE];
 
-static void print_device_addr(char *ethaddr) {
-    PrintDebug("Vnet: print_device_addr: ");
-    v3_hexdump(ethaddr, 6, NULL, 0);
-} 
-#endif
+    uint32_t num_routes;
+    struct vnet_route_info * routes[0];
+} __attribute__((packed));
 
 
-//network connection functions 
-static inline void ethernet_packet_init(struct ethernet_pkt *pt, const char *data, const size_t size) 
-{
-    pt->size = size;
-    memcpy(pt->data, data, size);
-}
 
-static uint_t hash_from_key_fn(addr_t hashkey) 
-{    
-    uint8_t * key = (uint8_t *)hashkey;
-    return v3_hash_buffer(key, HASH_KEY_LEN);
-}
+static struct {
+    struct list_head routes;
+    struct list_head devs;
 
-static int hash_key_equal(addr_t key1, addr_t key2) 
-{
-    uint8_t * buf1 = (uint8_t *)key1;
-    uint8_t * buf2 = (uint8_t *)key2;
-    return (memcmp(buf1, buf2, HASH_KEY_LEN) == 0);
-}
+    int num_routes;
+    int num_devs;
 
-static int init_route_cache() 
-{
-    g_route_cache = v3_create_htable(MIN_CACHE_SIZE, &hash_from_key_fn, &hash_key_equal);
+    v3_lock_t lock;
 
-    if (g_route_cache == NULL){
-        PrintError("Vnet: Route Cache Initiate Failurely\n");
-        return -1;
-    }
+    struct gen_queue * inpkt_q;
+    struct hashtable * route_cache;
 
-    return 0;
-}
+} vnet_state;
 
-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;
 
-    *(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;
-    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;
-    }
+/* 
+ * 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);
     
-    new_entry->num_matched_routes = num_matched_r;
+    return v3_hash_buffer(hdr_buf, VNET_HASH_SIZE);
+}
 
-    new_entry->matches = (int *)V3_Malloc(num_matched_r * sizeof(int));
-    
-    if (new_entry->matches == NULL){
-       PrintError("Vnet: Malloc fails\n");
+static inline int hash_eq(addr_t key1, addr_t key2) {
+    return (memcmp((uint8_t *)key1, (uint8_t *)key2, VNET_HASH_SIZE) == 0);
+}
+
+
+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);    
+
+    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");
        return -1;
     }
     
-    for (i = 0; i < num_matched_r; i++) {
-       new_entry->matches[i] = matches[i];
-    }
-    
-    //here, when v3_htable_insert return 0, it means insert fails
-    if (v3_htable_insert(g_route_cache, (addr_t)hashkey, (addr_t)new_entry) == 0){
-       PrintError("Vnet: Insert new route entry to cache failed\n");
-       V3_Free(new_entry->matches);
-       V3_Free(new_entry);
-    }
-    
     return 0;
 }
 
-static int clear_hash_cache() 
-{
-    v3_free_htable(g_route_cache, 1, 1);
-               
-    g_route_cache = v3_create_htable(MIN_CACHE_SIZE, hash_from_key_fn, hash_key_equal);
-    
-    if (g_route_cache == NULL){
-        PrintError("Vnet: Route Cache Create Failurely\n");
-        return -1;
-    }
+static int clear_hash_cache() {
+
+    /* 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) 
-{
-    int n_matches = -1;
-    int i = 0;
-    struct route_cache_entry * found = NULL;
+static int look_into_cache(struct v3_vnet_pkt * pkt, struct route_list ** routes) {
     
-    found = (struct route_cache_entry *)v3_htable_search(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;
 }
 
-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;
 
-    for (k = 0; k < 6; k++) {
-       mac[k] = hex_byte_to_byte(&(str[(2 * k) + k]));
-    }
-}
 
-static inline void mac_to_string(char mac[6], char * buf) 
-{
-    snprintf(buf, 20, "%x:%x:%x:%x:%x:%x", 
-            mac[0], mac[1], mac[2],
-            mac[3], mac[4], mac[5]);
-}
+int v3_vnet_add_route(struct v3_vnet_route route) {
+    struct vnet_route_info * new_route = NULL;
+    unsigned long flags; 
 
-static int add_link_entry(struct link_entry *link)
-{ 
-    int idx;
-    
-    for (idx = 0; idx < MAX_LINKS; idx++) {
-       if (g_links.links[idx] == NULL) {
-           g_links.links[idx] = link;
-           g_links.size ++;
-           
-           return idx;
-       }
-    }
-    
-    return -1;
-}
+    new_route = (struct vnet_route_info *)V3_Malloc(sizeof(struct vnet_route_info));
+    memset(new_route, 0, sizeof(struct vnet_route_info));
 
-static int add_route_entry(struct routing_entry *route)
-{ 
-    int idx;
-    
-    for (idx = 0; idx < MAX_ROUTES; idx++) {
-       if (g_routes.routes[idx] == NULL) {
-           g_routes.routes[idx] = route;
-           g_routes.size ++;
-           
-           return idx;
-       }
-    }
+    PrintDebug("Vnet: vnet_add_route_entry\n");        
     
-    return -1;
-}
-
+    new_route->route_def = route;
 
-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)
-{
-    struct routing_entry *new_route = (struct routing_entry *)V3_Malloc(sizeof(struct routing_entry));
-
-    memset(new_route, 0, sizeof(struct routing_entry));
-
-    if ((src_mac_qual != MAC_ANY) && (src_mac_qual != MAC_NONE)) {
-        memcpy(new_route->src_mac, src_mac, 6);
+    /* TODO: Find devices */
+    if (new_route->route_def.dst_type == LINK_INTERFACE) {
+       // new_route->dst_dev = FIND_DEV();
     }
-           
-    if ((dest_mac_qual != MAC_ANY) && (dest_mac_qual != MAC_NONE)) {
-        memcpy(new_route->dest_mac, dest_mac, 6);
+
+    if (new_route->route_def.src_type == LINK_INTERFACE) {
+       // new_route->src_dev = FIND_DEV()
     }
-           
-    new_route->src_mac_qual = src_mac_qual;
-    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;
-
-    int idx = -1;
-    if ((idx = add_route_entry(new_route)) == -1)
-        return -1;
-    
+
+    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();
-    
-    return idx;
-}
 
-static void * delete_link_entry(int index) 
-{
-    struct link_entry *link = NULL;
-    void *ret = NULL;
-    link_type_t type;
-  
-    if (index >= MAX_LINKS || g_links.links[index] == NULL) {
-       return NULL;
-    }
+    return 0;
+}
 
-    link = g_links.links[index];
-    type = g_links.links[index]->type;
 
-    if (type == LINK_INTERFACE)        
-       ret = (void *)g_links.links[index]->dst_dev;
-    else if (type == LINK_EDGE)
-       ret = (void *)g_links.links[index]->dst_link;
 
-    g_links.links[index] = NULL;
-    g_links.size --;
+// 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;
 
-    V3_Free(link);
-       
-    return ret;
-}
+#ifdef CONFIG_DEBUG_VNET
+    {
+       char dst_str[18];
+       char src_str[18];
 
-static int find_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 i;
-    char temp_src_mac[6];
-    char temp_dest_mac[6];
-  
-    if ((src_mac_qual != MAC_ANY) && (src_mac_qual != MAC_NONE)) {
-       memcpy(temp_src_mac, src_mac, 6);
-    } else {
-       memset(temp_src_mac, 0, 6);
-    }
-    
-    if ((dest_mac_qual != MAC_ANY) && (dest_mac_qual != MAC_NONE)) {
-       memcpy(temp_dest_mac, dest_mac, 6);
-    } else {
-       memset(temp_dest_mac, 0, 6);
+       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);
     }
+#endif
+
+    INIT_LIST_HEAD(&match_list);
     
-    for (i = 0; i<MAX_ROUTES; i++) {
-       if (g_routes.routes[i] != NULL) {
-           if ((memcmp(temp_src_mac, g_routes.routes[i]->src_mac, 6) == 0) && 
-                 (memcmp(temp_dest_mac, g_routes.routes[i]->dest_mac, 6) == 0) &&
-                 (g_routes.routes[i]->src_mac_qual == src_mac_qual) &&
-                 (g_routes.routes[i]->dest_mac_qual == dest_mac_qual)  &&
-                 ((link_type == LINK_ANY) || 
-                 ((link_type == g_routes.routes[i]->link_type) && (g_routes.routes[i]->link_idx == link_idx))) &&
-                 ((src_type == LINK_ANY) || 
-                 ((src_type == g_routes.routes[i]->src_type) && (g_routes.routes[i]->src_link_idx == src)))) {
-               return i;
-           }
-        } 
-     }
+#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 -1;
-}
-
-static int delete_route_entry(int index) 
-{
-    struct routing_entry *route;
 
-    if (index >= MAX_ROUTES || g_routes.routes[index] == NULL)
-               return -1;
 
-    route = g_routes.routes[index];
-    g_routes.routes[index] = NULL;
-    g_routes.size --;
+    list_for_each_entry(route, &(vnet_state.routes), node) {
+       struct v3_vnet_route * route_def = &(route->route_def);
 
-    V3_Free(route);
+       // 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;
+       }
 
-    clear_hash_cache();
-    
-    return 0;
-}
 
-int vnet_delete_route_entry_by_addr(char src_mac[6], 
-                                   char dest_mac[6], 
-                                   int src_mac_qual, 
-                                   int dest_mac_qual, 
-                                   int link_idx, 
-                                   link_type_t type, 
-                                   int src, 
-                                   link_type_t src_type) 
-{
-    int index = find_route_entry(src_mac, dest_mac, src_mac_qual, 
-                                dest_mac_qual, link_idx, type, src, src_type);
-    
-    if (index == -1) {
-       return -1;
-    }
-    
-    return delete_route_entry(index);
-}
-
-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 matched_routes[MAX_ROUTES];
-    
-    int num_matches = 0;
-    int i;
-    int max = 0;
-    int no = 0;
-    int exact_match = 0;
-
-    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]->dest_mac_qual == MAC_ANY) &&
-                (g_routes.routes[i]->src_mac_qual == MAC_ANY)) {      
-                 matched_routes[num_matches] = i;
-                 values[num_matches] = 3;
-                 num_matches++;
-           }
+       if ((route_def->dst_mac_qual == MAC_ANY) &&
+           (route_def->src_mac_qual == MAC_ANY)) {      
+           UPDATE_MATCHES(3);
+       }
        
-           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(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 (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(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);
+               }
            }
-       
-           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 ((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 ((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++;
-                     }
-                }
+       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);
            }
-       }
-    }//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++;
-       }
-    }
-    
-    return no;
-}
-
-#if 0
-// TODO: To be removed
-static int process_udpdata() 
-{
-    struct ethernet_pkt * pt;
-
-    uint32_t dest = 0;
-    uint16_t remote_port = 0;
-    SOCK link_sock = g_udp_sockfd;
-    int length = sizeof(struct ethernet_pkt) - (2 * sizeof(int));   //minus the "size" and "type" 
-
-    //run in a loop to get packets from outside network, adding them to the incoming packet queue
-    while (1) {
-       pt = (struct ethernet_pkt *)V3_Malloc(sizeof(struct ethernet_pkt));
-
-       if (pt == NULL){
-           PrintError("Vnet: process_udp: Malloc fails\n");
-           continue;
        }
        
-       PrintDebug("Vnet: route_thread: socket: [%d]. ready to receive from ip [%x], port [%d] or from VMs\n", link_sock, (uint_t)dest, remote_port);
-       pt->size = V3_RecvFrom_IP( link_sock, dest, remote_port, pt->data, length);
-       PrintDebug("Vnet: route_thread: socket: [%d] receive from ip [%x], port [%d]\n", link_sock, (uint_t)dest, remote_port);
-       
-       if (pt->size <= 0) {
-           PrintDebug("Vnet: process_udp: receiving packet from UDP fails\n");
-           V3_Free(pt);
-           return -1;
+       // Default route
+       if ( (memcmp(route_def->src_mac, hdr->src_mac, 6) == 0) &
+            (route_def->dst_mac_qual == MAC_NONE)) {
+           UPDATE_MATCHES(4);
        }
-       
-       PrintDebug("Vnet: process_udp: get packet\n");
-       print_packet(pt->data, pt->size);
     }
-}
 
-// TODO: To be removed
-static int indata_handler( )
-{
-      if (!use_tcp)
-          process_udpdata();     
+    PrintDebug("Vnet: match_route: Matches=%d\n", num_matches);
 
-      return 0;   
-}
+    if (num_matches == 0) {
+       return NULL;
+    }
 
-// TODO: To be removed
-static int start_recv_data()
-{
-       if (use_tcp){
-               
-       } else {
-               SOCK udp_data_socket;
-  
-               if ((udp_data_socket = V3_Create_UDP_Socket()) < 0){
-                       PrintError("VNET: Can't setup udp socket\n");
-                       return -1; 
-               }
-               PrintDebug("Vnet: vnet_setup_udp: get socket: %d\n", udp_data_socket);
-               g_udp_sockfd = udp_data_socket;
-
-               store_topologies(udp_data_socket);
-
-               if (V3_Bind_Socket(udp_data_socket, vnet_udp_port) < 0){ 
-                       PrintError("VNET: Can't bind socket\n");
-                       return -1;
-               }
-               PrintDebug("VNET: vnet_setup_udp: bind socket successful\n");
-       }
+    matches = V3_Malloc(sizeof(struct route_list) + 
+                       (sizeof(struct vnet_route_info *) * num_matches));
 
-       V3_CREATE_THREAD(&indata_handler, NULL, "VNET_DATA_HANDLER");
-       return 0;
-}
+    matches->num_routes = num_matches;
 
-static void store_test_topologies(SOCK fd) 
-{
-    int i;
-    int src_mac_qual = MAC_ANY;
-    int dest_mac_qual = MAC_ANY;
-    uint_t dest;
-#ifndef VNET_SERVER
-    dest = (0 | 172 << 24 | 23 << 16 | 1 );
-    PrintDebug("VNET: store_topologies. NOT VNET_SERVER, dest = %x\n", dest);
-#else
-    dest = (0 | 172 << 24 | 23 << 16 | 2 );
-    PrintDebug("VNET: store_topologies. VNET_SERVER, dest = %x\n", dest);
-#endif
+    {
+       int i = 0;
+       list_for_each_entry(route, &match_list, node) {
+           matches->routes[i++] = route;
+       }
+    }
 
-    int type = UDP_TYPE;
-    int src = 0;
-    int src_type= LINK_ANY; //ANY_SRC_TYPE
-    int data_port = 22;
+    return matches;
 }
 
-#endif
-
-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
+static int handle_one_pkt(struct v3_vnet_pkt * pkt) {
+    struct route_list * matched_routes = NULL;
     int i;
-    char src_mac[6];
-    char dst_mac[6];
-
-    int matches[MAX_ROUTES];
-    int num_matched_routes = 0;
 
-    struct in_pkt_header header;
-  
-    // 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
+
+    look_into_cache(pkt, &matched_routes);
     
-    char hash_key[hash_key_size];
-    make_hash_key(hash_key, src_mac, dst_mac, LINK_EDGE, src_link_index);//link_edge -> pt->type???
-    
-    num_matched_routes = look_into_cache((route_hashkey_t)hash_key, matches);
-    
-    if (num_matched_routes == -1) {  //no match
-        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);
     
-    for (i = 0; i < num_matched_routes; i++) {
-        int route_index = -1;
-        int link_index = -1;
-        int pkt_len = 0;
-       
-        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)
-            continue;
-        
-        struct link_entry *link = g_links.links[link_index];
-        if (link == NULL)
-            continue;
-        
-        pkt_len = pkt->size;
-        if (g_routes.routes[route_index]->link_type == LINK_EDGE) {
-
-            // TODO: apply the header in the beginning of the packet to be sent
-            if ((link->dst_link->input(pkt->data, pkt_len, NULL)) != pkt_len)
-                return -1;
-        } else if (g_routes.routes[route_index]->link_type == LINK_INTERFACE) {
-          
-      
-            if ((link->dst_link->input(pkt->data, pkt_len, NULL)) != pkt_len)
-                return -1;
-        } else {
-            PrintError("Vnet: Wrong Edge type\n");
-            return -1;
-        }
-    }
-
-     return 0;
-}
-
-static int send_ethernet_pkt(char *buf, int length) 
-{
-       struct ethernet_pkt *pt;
+    for (i = 0; i < matched_routes->num_routes; i++) {
+       struct vnet_route_info * route = matched_routes->routes[i];
 
-       pt = (struct ethernet_pkt *)V3_Malloc(sizeof(struct ethernet_pkt));
-       ethernet_packet_init(pt, buf, length);  //====here we copy sending data once 
-       
-       PrintDebug("VNET: vm_send_pkt: transmitting packet: (size:%d)\n", (int)pt->size);
-       print_packet((char *)buf, length);
-       
-       v3_enqueue(g_inpkt_q, (addr_t)pt);
+        if (route->route_def.dst_type == LINK_EDGE) {
 
-       return 0;
-}
+        } 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\n");
+            continue;
+        }
 
-int v3_vnet_send_pkt(uchar_t *buf, int length) 
-{
-    PrintDebug("VNET: In V3_Send_pkt: pkt length %d\n", length);
+        PrintDebug("Vnet: HandleDataOverLink: Forward packet according to Route\n");
+    }
     
-    return send_ethernet_pkt((char *)buf, length);
+    return 0;
 }
 
-static int search_device(char *device_name) 
-{
-    int i;
+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(pkt);
+#endif
 
-    for (i = 0; i < MAX_LINKS; i++) {
-        if (g_links.links[i] != NULL && g_links.links[i]->type == LINK_INTERFACE) {
-           if (!strcmp(device_name, g_links.links[i]->dst_dev->name)) {
-               return i;
-           }
-        }
-    }
-    
-    return -1;
+    return 0;
 }
 
-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) 
-{
-    struct vnet_if_device *if_dev;
 
-    int idx = search_device(dev_name);
-    if (idx != -1)
-       return -1;
+/*
+static struct vnet_dev * find_dev_by_id(int idx) {
     
-    if_dev = (struct vnet_if_device *)V3_Malloc(sizeof(struct vnet_if_device));
-    
-    if (if_dev == NULL){
-       PrintError("VNET: Malloc fails\n");
-       return -1;
-    }
-    
-    strcpy(if_dev->name, dev_name);
-    strncpy(if_dev->mac_addr, mac, 6);
-    if_dev->dev = vdev;
-    if_dev->input = netif_input;
-    if_dev->private_data = data;
 
-    struct link_entry *link = (struct link_entry *)V3_Malloc(sizeof(struct link_entry));
+    // scan device list
+    return NULL;
+}
+*/
 
-    link->type = LINK_INTERFACE;
-    link->dst_dev = if_dev;
+static struct vnet_dev * find_dev_by_name(char * name) {
 
-    idx = add_link_entry(link);
-    
-    return idx;
+    return NULL;
 }
 
-int vnet_unregister_device(char *dev_name) 
-{
-    int idx;
+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_dev * new_dev = NULL;
 
-    idx = search_device(dev_name);
-    
-    if (idx == -1) {
-        return -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;
     }
+    
+    new_dev = (struct vnet_dev *)V3_Malloc(sizeof(struct vnet_dev)); 
 
-    struct vnet_if_device *device = (struct vnet_if_device *)delete_link_entry(idx);
-    if (device == NULL) {
+    if (new_dev == NULL) {
+       PrintError("VNET: Malloc fails\n");
        return -1;
     }
+    
+    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;
 
-    V3_Free(device);
+    // ADD TO dev list
+    // increment dev count
 
-    return idx;
+    return 0;
 }
 
-int v3_vnet_pkt_process() 
-{
-    struct ethernet_pkt *pt;
+int v3_vnet_pkt_process() {
+    struct v3_vnet_pkt * pkt = NULL;
 
-    PrintDebug("VNET: In vnet_check\n");
-       
-    while ((pt = (struct ethernet_pkt *)v3_dequeue(g_inpkt_q)) != NULL) {
-       PrintDebug("VNET: In vnet_check: pt length %d, pt type %d\n", (int)pt->size, (int)pt->type);
-       v3_hexdump(pt->data, pt->size, NULL, 0);
-       
-       if(handle_one_pkt(pt)) {
-           PrintDebug("VNET: vnet_check: handle one packet!\n");  
-       }else {
-           PrintError("VNET: vnet_check: fail to forward one packet, discard it!\n"); 
-       }
+    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 {
+            PrintDebug("VNET: vnet_check: Fail to forward one packet, discard it!\n"); 
+        }
        
-       V3_Free(pt); //be careful here
+        V3_Free(pkt); // be careful here
     }
     
     return 0;
 }
 
 
-static void init_empty_link_table() 
-{
-    int i;
+int V3_init_vnet() {
 
-    for (i = 0; i < MAX_LINKS; i++)
-        g_links.links[i] = NULL;
+    PrintDebug("VNET: Links table initiated\n");
 
-       
-    g_links.size = 0;
-}
+    INIT_LIST_HEAD(&(vnet_state.routes));
 
-static void init_empty_route_table() 
-{      
-    int i;
+    if (v3_lock_init(&(vnet_state.lock)) == -1){
+        PrintError("VNET: Failure to init lock for routes table\n");
+    }
 
-    for (i = 0; i < MAX_ROUTES; i++) 
-        g_routes.routes[i] = NULL;
+    PrintDebug("VNET: Routes table initiated\n");
 
-    g_links.size = 0;
-}
+    /*initial pkt receiving queue */
+    vnet_state.inpkt_q = v3_create_queue();
+    v3_init_queue(vnet_state.inpkt_q);
+    PrintDebug("VNET: Receiving queue initiated\n");
 
-static void init_tables() {
-    init_empty_link_table();
-    init_empty_route_table();
-    init_route_cache();
-}
+    vnet_state.route_cache = v3_create_htable(0, &hash_fn, &hash_eq);
 
-static void init_pkt_queue()
-{
-    PrintDebug("VNET Init package receiving queue\n");
+    if (vnet_state.route_cache == NULL) {
+        PrintError("Vnet: Route Cache Init Fails\n");
+        return -1;
+    }
 
-    g_inpkt_q = v3_create_queue();
-    v3_init_queue(g_inpkt_q);
+    return 0;
 }
 
-#if 0
-// TODO: 
-static int init_routing_tables(struct routing_entry *route_tab, uint16_t size)
-{
-    //struct routing_entry *route;
 
 
-    return 0;
-}
+#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);
+}
 
-// TODO: 
-static int init_link_tables(struct link_entry *link_tab, uint16_t size)
-{
-    //struct link_entry *link;
 
-    return 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]);
 }
 
-#endif
 
-struct table_init_info {
-    addr_t routing_table_start;
-    uint16_t routing_table_size;
-    addr_t link_table_start;
-    uint16_t link_table_size;
-};
-
-static int handle_init_tables_hcall(struct guest_info * info, uint_t hcall_id, void *priv_data) 
-{
-    uint8_t *buf = NULL;
-    addr_t info_addr = (addr_t)info->vm_regs.rcx;
+static void print_route(struct routing_entry *route){
+    char dest_str[18];
+    char src_str[18];
 
-    if (guest_va_to_host_va(info, info_addr, (addr_t *)&(buf)) == -1) {
-       PrintError("Could not translate buffer address\n");
-       return -1;
-    }
+    mac_to_string(route->src_mac, src_str);  
+    mac_to_string(route->dest_mac, dest_str);
 
-    //struct table_init_info *init_info = (struct table_init_info *)buf;
-    
-    
-    return 0;
+    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);
 }
+       
 
+static void dump_routes(struct routing_entry **route_tables) {
+    int i;
 
-void v3_vnet_init(struct guest_info *vm) 
-{
-    init_tables();
-    init_pkt_queue();
-       
-    v3_register_hypercall(vm, VNET_INITAB_HCALL, handle_init_tables_hcall, NULL);
+    PrintDebug("\nVnet: route table dump start =====\n");
 
-    //store_test_topologies(udp_data_socket); 
+    for(i = 0; i < MAX_ROUTES; i++) {
+        if (route_tables[i] != NULL){
+            print_route(route_tables[i]);
+        }
+    }
 
-    PrintDebug("VNET Initied\n");
+    PrintDebug("\nVnet: route table dump end =====\n");
 }
 
-
+#endif