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 Code Cleaned
Lei Xia [Wed, 28 Oct 2009 21:08:00 +0000 (16:08 -0500)]
palacios/include/devices/vnet.h
palacios/src/devices/vnet.c

index c418035..f76dbd1 100644 (file)
  * All rights reserved.
  *
  * Author: Lei Xia <lxia@northwestern.edu>
- *            Yuan Tang <ytang@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".
  */
-#if 0
 
 #ifndef __VNET_H__
 #define __VNET_H__
 #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)
 
-
-struct gen_queue * vnet_inpkt_q;
-
 struct ethAddr{
   char addr[6];
 };
 
-typedef struct vnet_device{
-       char name[50];
-//     struct ethAddr device_addr;
-       int (*input)(uchar_t * pkt, uint_t size);
-
-       void *data;
-       //....
-}iface_t;
-
-#define ROUTE 1
-//#define ROUTE 0
-
-#if ROUTE //new routing accrding to VNET-VTL, no hash --YT
-
-//struct gen_queue *src_link_index_q;
-
 #define SOCK int
-#define MAX_LINKS 100
-#define MAX_ROUTES 500
-#define MAX_DEVICES 16
 
 #define TCP_TYPE 0
 #define UDP_TYPE 1
@@ -79,15 +55,6 @@ typedef struct vnet_device{
 #define HANDLER_ERROR -1
 #define HANDLER_SUCCESS 0
 */
-/* These are the return codes for the Control Session */
-/*
-#define CTRL_DO_NOTHING 0
-#define CTRL_CLOSE 1
-#define CTRL_DELETE_TCP_SOCK 3
-#define CTRL_ADD_TCP_SOCK 4
-#define CTRL_EXIT 5
-#define CTRL_ERROR -1
-*/
 
 #define ANY "any"
 #define NOT "not"
@@ -107,7 +74,7 @@ typedef struct vnet_device{
 #define EDGE_TYPE 1
 #define ANY_SRC_TYPE 2
 
-//This is the structure that stores the routing entries
+//the routing entry
 struct routing {
   char src_mac[6];
   char dest_mac[6];
@@ -137,10 +104,9 @@ struct topology {
   unsigned short remote_port;
 
   // LINK OR GATEWAY
-//  int link_class;
+  // int link_class;
 
   int use;
-//  int authenticated;
   int type; //TCP=0, UDP=1,VTP=2, can be extended so on
 
   int next;
@@ -154,15 +120,24 @@ struct sock_list {
   int prev;
 };
 
-typedef struct sock_list con_t;
 
-struct device_list {
-  char *device_name;
+#define GENERAL_NIC 0
+
+struct vnet_if_device{
+       char name[50];
+       struct ethAddr device_addr;
 
-  iface_t * vnet_device;
+       int (*input)(uchar_t * pkt, uint_t size);
+
+       void *data;
+};
+
+
+struct device_list {
+  struct vnet_if_device *device;
 
-  int type;
   int use;
+  int type;
 
   int next;
   int prev;
@@ -177,13 +152,11 @@ struct HEADERS {
 };
 
 #define FOREACH(iter, list, start) for (iter = start; iter != -1; iter = list[iter].next)
-
 #define FOREACH_SOCK(iter, socks, start) FOREACH(iter, socks, start)
 #define FOREACH_LINK(iter, links, start) FOREACH(iter, links, start)
 #define FOREACH_ROUTE(iter, routes, start) FOREACH(iter, routes, start)
 #define FOREACH_DEVICE(iter, devices, start) FOREACH(iter, devices, start)
 
-#endif
 
 int V3_Send_pkt(uchar_t *buf, int length);
 int V3_Register_pkt_event(int (*netif_input)(uchar_t * pkt, uint_t size));
@@ -192,12 +165,10 @@ int V3_Register_pkt_event(int (*netif_input)(uchar_t * pkt, uint_t size));
 int vnet_send_pkt(char *buf, int length);
 int vnet_register_pkt_event(char *dev_name, int (*netif_input)(uchar_t * pkt, uint_t size), void *data);
 
-//check if there are incoming packet in the queue for VNIC, if yes, send the packet to the VNIC
-//this should put in the svm exit handler
-int vnet_check();
+int vnet_pkt_process();
 
 void vnet_init();
 
 #endif
-#endif
+
 
index 500af1d..d8c64f3 100644 (file)
  * 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, Peter Dinda <pdinda@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>
+ *               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 <devices/vnet.h>
 
-#define MAX_ADDRESS 10
-typedef enum {LOCAL,REMOTE} ctype;
-
-struct handler{
-  int    fd;
-  int local_address;
-  short  local_port;
-  struct vnet_device *local_device;
-  int remote_address;
-  short  remote_port;
-  struct vnet_device *remote_device;
-  struct ethAddr addresses[MAX_ADDRESS];
-  ctype local_config;
-  ctype remote_config; 
+struct raw_ethernet_pkt {
+  int  size;
+  int type; // vm or link type:  INTERFACE|EDGE
+  char  data[ETHERNET_PACKET_LEN];
 };
 
+char *vnet_version = "0.9";
+static int vnet_server = 0;
+static bool use_tcp = false;
 
-typedef struct {
-  int  size;
-  char  data[ETHERNET_PACKET_LEN];
-  int index;
-}RawEthernetPacket;
+static uint_t vnet_udp_port = 22;
 
+#define MAX_LINKS 1
+#define MAX_ROUTES 1
+#define MAX_DEVICES 16
 
-#define NUM_DEVICES 1
-#define NUM_HANDLERS 1
 
-static struct vnet_device *available_devices[NUM_DEVICES];
+struct topology g_links[MAX_LINKS];
+int g_num_links; //The current number of links
+int g_first_link;
+int g_last_link;
 
-struct handler *active_handlers[NUM_HANDLERS];
+struct routing g_routes[MAX_ROUTES];
+int g_num_routes; //The current number of routes
+int g_first_route;
+int g_last_route;
 
-static int bind_address = 0;
-static short  bind_port = 22;
-//static char *vnet_version = "0.9";
-static int vnet_server = 0;
-static bool use_tcp = false;
+struct device_list g_devices[MAX_DEVICES];
+int g_num_devices;
+int g_first_device;
+int g_last_device;
 
+SOCK g_udp_sockfd;
+static struct gen_queue * g_inpkt_q;//packet receiving queue
 
 
 static void print_packet(char *pkt, int size)
 {
       int i;
           
-       PrintDebug("Vnet: packet: size: %d\n", size);
+       PrintDebug("Vnet: print_data_packet: size: %d\n", size);
        for (i = 0; i < size; i ++)
                PrintDebug("%x ", pkt[i]);
        PrintDebug("\n");
 }
 
-
-#if !(ROUTE)
-static struct vnet_device *get_device(RawEthernetPacket *pt)
-{
-       return available_devices[0];
-}
-#endif
-
-static struct handler * get_handler()
-{
-       
-       return active_handlers[0];
-}
-
-static inline bool add_handler(struct handler *hd)
+#if 0
+static void print_packet_addr(char *pkt)
 {
-       int num = 0;
+       int i;
           
-       while (active_handlers[num] != NULL) num ++;
-
-       if (num >= NUM_HANDLERS)
-               return false;
-
-       active_handlers[num] = hd;
-
-       return true;
+       PrintDebug("Vnet: print_packet_destination_addr: ");
+       for (i = 8; i < 14; i ++)
+               PrintDebug("%x ", pkt[i]);
+       PrintDebug("\n");
+       
+       PrintDebug("Vnet: print_packet_source_addr: ");
+       for (i = 14; i < 20; i ++)
+               PrintDebug("%x ", pkt[i]);
+       PrintDebug("\n");
 }
 
-static inline bool add_device(struct vnet_device *dev)
+static void print_device_addr(char *ethaddr)
 {
-       int num = 0;
+      int i;
           
-       while (available_devices[num] != NULL) num ++;
-
-       if (num >= NUM_DEVICES)
-               return false;
-
-       available_devices[num] = dev;
-
-       return true;
-}
+       PrintDebug("Vnet: print_device_addr: ");
+       for (i = 0; i < 6; i ++)
+               PrintDebug("%x ", ethaddr[i]);
+       PrintDebug("\n");
+} 
+#endif
 
+//network connection functions 
 
-int CreateAndSetupTcpSocket(const int bufsize, const bool nodelay, const bool nonblocking)
+#if 0
+static int CreateAndSetupTcpSocket(const int bufsize, const bool nodelay, const bool nonblocking)
 {
   int mysocket;
 
@@ -129,7 +113,7 @@ int CreateAndSetupTcpSocket(const int bufsize, const bool nodelay, const bool no
   return mysocket;
 }
 
-int BindSocketwPort(const int mysocket, const int myport)
+static int BindSocketwPort(const int mysocket, const int myport)
 {
    if (V3_Bind_Socket(mysocket, myport) < 0) {
     return -1;
@@ -138,431 +122,201 @@ int BindSocketwPort(const int mysocket, const int myport)
   return 0;
 }  
 
-int ListenSocket(const int mysocket, const int maxc)
+static int ListenSocket(const int mysocket, const int maxc)
 {
   return V3_Listen_Socket(mysocket, maxc);
 }
 
-int ConnectToHost(const int mysocket, const int hostip, const int port)
+static int ConnectToHost(const int mysocket, const int hostip, const int port)
 {
   return V3_Connect_To_IP(mysocket, hostip, port);
 }
 
-/*
-void close(int mysocket)
+
+static void close(int mysocket)
 {
   V3_Close_Socket(mysocket);
 }
-*/
 
-#if 0 //May be needed later
-int SendTo(int const mysocket, 
-           const unsigned ip, const int port, 
-           const char *buf, const int len, const bool sendall)
+static int raw_ethernet_pkt_sendUdp(struct raw_ethernet_pkt *pt, int sock_fd, int ip, short port)
 {
-  int left;
-  int sent;
-
-  if (!sendall) {
-    return V3_SendTo_IP(mysocket, ip, port, buf, len);
-  } else {
-    left = len;
-
-    while (left>0) {
-      sent = V3_SendTo_IP(mysocket, ip, port, buf, len);
-      if (sent < 0) {  
-          return -1;
-      } else {
-        left-=sent;
-      }
-    }
-    return len;
-  }
-}
+    int size;
 
-
-int ReceiveFrom(const int mysocket, 
-                const unsigned ip, const int port, 
-                char *buf, const int len,
-                const bool recvall)
-{
-    int left;  
-    int received;
+    PrintDebug("Vnet: sending by UDP socket %d  ip: %x,  port: %d\n", sock_fd, ip, port);
   
-    if (!recvall) {
-       return V3_RecvFrom_IP(mysocket, ip, port, buf, len);
-    } else {
-       left = len;     
-
-       while (left > 0) {
-               received = V3_RecvFrom_IP(mysocket, ip, port, buf, len);
-               if (received < 0) {
-                       return -1;
-               } else if (received == 0) {
-                       break;
-               } else {        
-                       left -= received;
-               }
-       }
-       
-       return len-left;
+    if ((size = V3_SendTo_IP(sock_fd, ip, port, pt->data, pt->size)) != pt->size) {
+        PrintError("Vnet: sending by UDP Exception, %x\n", size);
+        return -1;
     }
+    return 0;
 }
 
-
-int Send(int socketfd, const char *buf, const int len, const bool sendall)
-{
-  int left;
-  int sent;
-
-  if (!sendall) {
-      return V3_Send(socketfd, buf, len);
-  } else  {
-      left = len;
-        
-      while (left>0) {
-          sent = V3_Send(socketfd, &(buf[len-left]), left);
-
-          if (sent < 0) {
-              return -1;
-          } else if (sent == 0) {
-              break;
-          } else {
-              left -= sent;
-          }
-      }
-         
-      return len-left;
-  }
-}
-
-int GetLine(int fd, char *buf, int size)
-{
-  int rc;
-  int received = 0;
-  char c;
-  
-  while (1) { 
-    rc = Receive(fd, &c, 1, true);
-    
-    if (rc < 0) { 
-      return rc;
-    } 
-       
-    if (rc == 0 || c == '\n') {
-      return received;
-    }
-       
-    buf[received] = c;
-    received += rc;
-
-    if (received >= size)
-       break;
-  }
-
-  return received;
-}
-
-
-int PutLine(int mysocket, char *buf, int size)
-{
-  buf[size] = '\n';
-  return (Send(mysocket, buf, size+1, true) - 1);
-}
 #endif
 
-
-static int readall(const int fd, char *buf, const int len, const int oneshot, const int awaitblock)
-{
-  int rc;
-  int left;
-
-  left = len;
-  
-  while (left > 0) {
-    rc = V3_Recv(fd, &(buf[len-left]), left);
-       
-    if (oneshot) { 
-      return rc;
-    }
-       
-    if (rc <= 0) { 
-      return rc;
-    } else {
-      left -= rc;
-    }
-  }
-  
-  return len;
-}
-
-static int writeall(const int fd, const char *buf, const int len, const int oneshot, const int awaitblock)
-{
-  int rc;
-  int left;
-
-  left = len;
-  
-  while (left > 0) {
-    rc = V3_Send(fd, &(buf[len-left]), left);
-
-    if (oneshot) { 
-      return rc;
-    }
-       
-    if (rc <= 0) { 
-      return rc;
-    } else {
-      left -= rc;
-    }
-  }
-  return len;
-}
-
-static void RawEthernetPacketInit(RawEthernetPacket *pt, const char *data, const size_t size)
+static void raw_ethernet_packet_init(struct raw_ethernet_pkt *pt, const char *data, const size_t size)
 {
   pt->size = size;
   memcpy(pt->data, data, size);
 }
 
-static bool RawEthernetPacketSerialize(RawEthernetPacket *pt, const int fd)
-{
-  if (writeall(fd,(char*)&(pt->size),sizeof(pt->size),0,1)!=sizeof(pt->size)) 
-    {
-      PrintError("Vnet: Serialization Exception\n");
-      return false;
-    }
-  if (writeall(fd,pt->data,pt->size,0,1)!=(int)(pt->size))
-    {
-      PrintError("Vnet: Serialization Exception\n");
-      return false;
-    }
-
-  return true;
-}
-
-static bool RawEthernetPacketUnserialize(RawEthernetPacket *pt, const int fd)
-{
-  if (readall(fd,(char*)&(pt->size),sizeof(pt->size),0,1) != sizeof(pt->size))
-    {
-      PrintError("Vnet: Unserialization Exception\n");
-      return false;
-    }
-  if (readall(fd,pt->data,pt->size,0,1) != pt->size)
-    {
-      PrintError("Vnet: Unserialization Exception\n");
-      return false;
-    }
-
-  return true;
-}
-
-static bool RawEthernetPacketSendUdp(RawEthernetPacket *pt, int sock_fd, int ip, short port)
-{
-  int size;
-
-  PrintDebug("Vnet: sending by UDP socket %d  ip: %x,  port: %d\n", sock_fd, ip, port);
-  
-  if ((size = V3_SendTo_IP(sock_fd, ip, port, pt->data, pt->size)) != pt->size) 
-    {
-      PrintError("Vnet: sending by UDP Exception, %x\n", size);
-      return false;
-    }
-  return true;
-}
-
-
-#if 0
-static void print_packet_addr(char *pkt)
-{
-       int i;
-          
-       PrintDebug("Vnet: print_packet_destination_addr: ");
-       for (i = 8; i < 14; i ++)
-               PrintDebug("%x ", pkt[i]);
-       PrintDebug("\n");
-       
-       PrintDebug("Vnet: print_packet_source_addr: ");
-       for (i = 14; i < 20; i ++)
-               PrintDebug("%x ", pkt[i]);
-       PrintDebug("\n");
-}
-
-/*
-static void print_device_addr(char *ethaddr)
-{
-      int i;
-          
-       PrintDebug("Vnet: print_device_addr: ");
-       for (i = 0; i < 6; i ++)
-               PrintDebug("%x ", ethaddr[i]);
-       PrintDebug("\n");
-}
-*/
-#endif
-
-
-#if ROUTE  //new routing accrding to VNET-VTL, no hash --TY
-
-struct topology g_links[MAX_LINKS];
-int g_num_links; //The current number of links
-int g_first_link;
-int g_last_link;
-
-struct routing g_routes[MAX_ROUTES];
-int g_num_routes; //The current number of routes
-int g_first_route;
-int g_last_route;
-
-struct device_list g_devices[MAX_DEVICES];
-int g_num_devices;
-int g_first_device;
-int g_last_device;
-
 #define in_range(c, lo, up)  ((char)c >= lo && (char)c <= up)
-#define islower(c)           in_range(c, 'a', 'z')
+//#define islower(c)           in_range(c, 'a', 'z')
 
-//------------------hash function begin-------------------
 
 #define HASH_KEY_SIZE 16
+#define MIN_CACHE_SIZE 100
+
 /* Hash key format:
  * 0-5:     src_eth_addr
  * 6-11:    dest_eth_addr
  * 12:      src type
  * 13-16:   src index
  */
- struct hash_key
-{
-       char *key_from_addr;
-};
+typedef char * route_hashkey_t;
 
-struct hash_value  // This is the hash value, defined as a dynamic array. Format: 0: num_matched_routes, 1...n: matches[] -- TY
+struct route_cache_entry  // This is the hash value, Format: 0: num_matched_routes, 1...n: matches[] -- TY
 {
-       int num_matched_routes;
-       int *matches; 
+    int num_matched_routes;
+    int *matches; 
 };
-/*
-    static int insert_some (struct hashtable * htable, struct hash_key *key, struct hash_value *value) { 
-       return hashtable_insert(htable, (addr_t)key, (addr_t)value);    
-    }
-*/
 
-DEFINE_HASHTABLE_INSERT(insert_some, struct hash_key *, struct hash_value *);
-DEFINE_HASHTABLE_SEARCH(search_some, struct hash_key *, struct hash_value);
-//DEFINE_HASHTABLE_REMOVE(remove_some, struct hash_key *, struct hash_value, 1);
-//DEFINE_HASHTABLE_ITERATOR_SEARCH(search_itr_some, struct key);
+struct hashtable *g_route_cache; //Header of the route cache
 
-struct hash_key *cache_key;   //maybe these three variables should be defined as local variable. -- TY
-struct hash_value *cache_entry;
-struct hashtable *hash_route;
-
-/*
-malloc_key_value()
+static uint_t hash_from_key_fn(addr_t hashkey)
 {
-cache_key = (hash_key *)V3_Malloc(sizeof(hash_key));
-addr_t key = *cache_key;
-}
-*/
- // This is the hash algorithm used for UNIX ELF object files
-inline size_t hash_from_key(const char * arg) 
-{
-    size_t hash = 0;
-    size_t temp = 0;
-
+    uint_t hash = 0;
+    uint_t temp = 0; 
     int i;
-    for(i = 0; i < HASH_KEY_SIZE; i++) {
-      hash = (hash << 4) + *(arg + i) + i;
-      if ((temp = (hash & 0xF0000000))) {
-       hash ^= (temp >> 24);
-      }
-      hash &= ~temp;
+
+    char *key =(char *)hashkey;
+
+    for (i = 0; i < HASH_KEY_SIZE; i++) {
+        hash = (hash << 4) + *(key + i) + i;
+        if ((temp = (hash & 0xF0000000))) {
+             hash ^= (temp >> 24);
+        }
+        hash &= ~temp;
     }
     PrintDebug("Hash Value: %lu\n", (unsigned long)hash);
+       
     return hash;
 }
 
-inline bool hash_key_equal(const char * left, const char * right)
+static int hash_key_equal(addr_t left, addr_t right)
 {
-      int i;
-      for(i = 0; i < HASH_KEY_SIZE; i++) {
-      if (left[i] != right[i]) {
-       PrintDebug("HASHes not equal\n");
-       return false;
-      }
+    int i;
+    char *key1, *key2;
+    key1 = (char *)left;
+    key2 = (char *)right;
+       
+    for(i = 0; i < HASH_KEY_SIZE; i++) {
+        if (key1[i] != key2[i]) {
+             PrintDebug("HASHes not equal\n");
+
+             return -1;
+        }
     }
-    return true;
+    return 0;
 }
 
-void make_hash_key(char * hash_key, char src_addr[6], char dest_addr[6], char src_type, int src_index) {
-  int j;
+static int init_route_cache()
+{
+    g_route_cache = v3_create_htable(MIN_CACHE_SIZE, &hash_from_key_fn, &hash_key_equal);
 
-  for(j = 0; j < 6; j++) {
-    hash_key[j] = src_addr[j];
-    hash_key[j + 6] = dest_addr[j] + 1;
-  }
+    if (g_route_cache == NULL){
+        PrintError("Vnet: Route Cache Initiate Failurely\n");
+        return -1;
+    }
 
-  hash_key[12] = src_type;
+    return 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;
 
-  *(int *)(hash_key + 12) = src_index;
+       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;
 }
 
-int AddMatchedRoutesToCache(int num_matched_r, int * matches)
+static int add_route_to_cache(route_hashkey_t hashkey, int num_matched_r, int *matches)
 {
-       cache_entry->num_matched_routes = num_matched_r;
+      struct route_cache_entry *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;
        int i;
-       for(i = 0; i < num_matched_r; i++) {
-               cache_entry->matches = (int *)V3_Malloc(sizeof(int));
-               *(cache_entry->matches) = matches[i];
+
+       new_entry->matches = (int *)V3_Malloc(num_matched_r*sizeof(int)); // TODO: Here need to consider where to release the memory when clear cache;
+
+       if (new_entry->matches == NULL){
+               PrintError("Vnet: Malloc fails\n");
+               return -1;
        }
-       if (!insert_some(hash_route, cache_key, cache_entry)) return -1; /*oom*/
+      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;
 }
 
-void clear_hash_cache() 
+static int clear_hash_cache() 
 {
-    hashtable_destroy(hash_route, 1, 1);  //maybe there are some problems.
-/*      hashtable_destroy(hash_route, 1, 1);
-        hash_route = NULL;
-        V3_Free(cache_key);
-        V3_Free(cache_entry);
-        cache_key = NULL;
-        cache_entry = NULL;
-*/
+    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;
+    }
+
+    return 0;
 }
 
-//int LookIntoCache(char compare_address[HASH_KEY_SIZE], int * do_we_analyze, int * matches) {
-int LookIntoCache(char compare_address[HASH_KEY_SIZE], int * matches) 
+static int look_into_cache(route_hashkey_t hashkey, int *matches) 
 {
-  int n_matches = 0;
-  int i;
-  struct hash_value *found;
-
-  cache_key->key_from_addr = compare_address;
-  if (NULL != (found = search_some(hash_route, cache_key))) {
-    n_matches = found->num_matched_routes;
-    for (i = 0; i < found->num_matched_routes; i++) {
-      //*(matches+i) = *(found->matches+i);
-      matches[i] = found->matches[i];
+    int n_matches = -1;
+    int i;
+    struct route_cache_entry *found;
+
+    found = (struct route_cache_entry *)v3_htable_search(g_route_cache, (addr_t)hashkey);
+   
+    if (found != NULL) {
+        n_matches = found->num_matched_routes;
+        for (i = 0; i < n_matches; i++)
+            matches[i] = found->matches[i];
     }
+
     return n_matches;
-  } else {
-    PrintDebug("VNET: LookIntoCache, hash key not found\n");
-    return -1;
-  }
 }
 
 
-//------------------hash function end-------------------
-
-char vnet_toupper(char c)
+static inline char vnet_toupper(char c)
 {
        if (islower(c))
                c -= 'a'-'A';
        return c;
 }
 
-char hexnybbletonybble(const char hexnybble) {
+static inline char hexnybbletonybble(const char hexnybble) {
   char x = vnet_toupper(hexnybble);
   if ((x >= '0') && (x <= '9')) {
     return x - '0';
@@ -571,28 +325,28 @@ char hexnybbletonybble(const char hexnybble) {
   }
 }
 
-void hexbytetobyte(const char hexbyte[2], char *byte) {
+static inline void hexbytetobyte(const char hexbyte[2], char *byte) {
   *byte = ((hexnybbletonybble(hexbyte[0]) << 4) + 
           (hexnybbletonybble(hexbyte[1]) & 0xf));
 }
 
-char nybbletohexnybble(const char nybble) {
+static inline char nybbletohexnybble(const char nybble) {
   return (nybble >= 10) ? (nybble - 10 + 'A') : (nybble + '0');
 }
 
-void bytetohexbyte(const char byte, char hexbyte[2]) {
+static inline void bytetohexbyte(const char byte, char hexbyte[2]) {
   hexbyte[0] = nybbletohexnybble((byte >> 4) & 0xf);
   hexbyte[1] = nybbletohexnybble(byte & 0xf);
 }
 
-void string_to_mac(const char * str, char mac[6]) {
+static inline void string_to_mac(const char * str, char mac[6]) {
   int k;
   for(k = 0; k < 6; k++) {
     hexbytetobyte(&(str[(2 * k) + k]), mac + k);
   }
 }
 
-void mac_to_string(char address[6], char * buf) {
+static inline void mac_to_string(char address[6], char * buf) {
   int i;
   for (i = 0; i < 6; i++) {
     bytetohexbyte(address[i], &(buf[3 * i]));
@@ -600,88 +354,79 @@ void mac_to_string(char address[6], char * buf) {
   }
   buf[17] = 0;
 }
+
 /*
-void ip_to_string(ulong_t addr, char * buf) {
-  struct in_addr addr_st;
+static void ip_to_string(ulong_t addr, char * buf) {
+  uint32_t addr_st;
   char * tmp_str;
 
-  addr_st.s_addr = htonl(addr);
-  tmp_str = inet_ntoa(addr_st);
+  addr_st = v3_htonl(addr);
+  tmp_str = v3_inet_ntoa(addr_st);
 
   memcpy(buf, tmp_str, strlen(tmp_str));
 }
 */
+
 int find_link_by_fd(SOCK sock) {
   int i;
 
   FOREACH_LINK(i, g_links, g_first_link) {
-    if (g_links[i].link_sock == sock) {
-      return i;
-    }
+      if (g_links[i].link_sock == sock) {
+          return i;
+      }
   }
 
   return -1;
 }
 
-int if_write_pkt(iface_t *iface, RawEthernetPacket *pkt)
-{
-   iface->input((uchar_t *)pkt->data, pkt->size);
-   return 0;
-}
-
-
-
-//int add_link_entry(unsigned long dest, int type, int link_class, int data_port, int authenticated, SOCK fd) {
-int add_link_entry(unsigned long dest, int type, int data_port,  SOCK fd) {
+int vnet_add_link_entry(unsigned long dest, int type, int data_port,  SOCK fd) {
   int i;
 
   for(i = 0; i < MAX_LINKS; i++) {
-    if (g_links[i].use == 0) {
-      g_links[i].dest = dest;
- //     g_links[i].authenticated = authenticated;
-      g_links[i].type = type;
-      g_links[i].link_sock = fd;
-      g_links[i].remote_port = data_port;
-      g_links[i].use = 1;
- //     g_links[i].link_class = link_class;
-
-      if (g_first_link == -1) 
-       g_first_link = i;
-
-      g_links[i].prev = g_last_link;
-      g_links[i].next = -1;
+      if (g_links[i].use == 0) {
+          g_links[i].dest = dest;
+          g_links[i].type = type;
+          g_links[i].link_sock = fd;
+          g_links[i].remote_port = data_port;
+          g_links[i].use = 1;
+          if (g_first_link == -1) 
+               g_first_link = i;
+
+          g_links[i].prev = g_last_link;
+          g_links[i].next = -1;
       
-      if (g_last_link != -1) {
-       g_links[g_last_link].next = i;
-      }
+          if (g_last_link != -1) {
+               g_links[g_last_link].next = i;
+          }
 
-      g_last_link = i;
+          g_last_link = i;
 
-      g_num_links++;
-      return i;
+          g_num_links++;
+
+           return i;
     }
   }
+  
   return -1;
 }
 
 
-
-
-int add_sock(struct sock_list * socks, int  len, int * first_sock, int * last_sock, SOCK fd) {
+// TODO: What is this used for?
+int add_sock(struct sock_list *socks, int  len, int *first_sock, int *last_sock, SOCK fd) {
   int i;
 
   for (i = 0; i < len; i++) {
-    if (socks[i].sock == -1) {
-      socks[i].sock = fd;
+      if (socks[i].sock == -1) {
+          socks[i].sock = fd;
 
       if (*first_sock == -1) 
-       *first_sock = i;
+           *first_sock = i;
 
       socks[i].prev = *last_sock;
       socks[i].next = -1;
 
       if (*last_sock != -1) 
-       socks[*last_sock].next = i;
+           socks[*last_sock].next = i;
 
       *last_sock = i;
 
@@ -692,454 +437,72 @@ int add_sock(struct sock_list * socks, int  len, int * first_sock, int * last_so
 }
 
 
-
-
-int add_route_entry(char src_mac[6], char dest_mac[6], int src_mac_qual, int dest_mac_qual, int dest, int type, int src, int src_type) {
+int vnet_add_route_entry(char src_mac[6], char dest_mac[6], int src_mac_qual, int dest_mac_qual, int dest, int type, int src, int src_type) {
   int i;
 
   for(i = 0; i < MAX_ROUTES; i++) {
-    if (g_routes[i].use == 0) {
+      if (g_routes[i].use == 0) {
      
-      if ((src_mac_qual != ANY_TYPE) && (src_mac_qual != NONE_TYPE)) {
-       memcpy(g_routes[i].src_mac, src_mac, 6);
-      } else {
-       memset(g_routes[i].src_mac, 0, 6);
-      }
-      
-      if ((dest_mac_qual != ANY_TYPE) && (dest_mac_qual != NONE_TYPE)) {
-       memcpy(g_routes[i].dest_mac, dest_mac, 6);
-      } else {
-       memset(g_routes[i].dest_mac, 0, 6);
-      }
-
-      g_routes[i].src_mac_qual = src_mac_qual;
-      g_routes[i].dest_mac_qual = dest_mac_qual;
-      g_routes[i].dest = dest;
-      g_routes[i].type = type;
-      g_routes[i].src = src;
-      g_routes[i].src_type = src_type;
+          if ((src_mac_qual != ANY_TYPE) && (src_mac_qual != NONE_TYPE)) {
+               memcpy(g_routes[i].src_mac, src_mac, 6);
+          } else {
+               memset(g_routes[i].src_mac, 0, 6);
+          }
       
-      g_routes[i].use = 1;
-
-      if (g_first_route == -1) 
-       g_first_route = i;
-
-      g_routes[i].prev = g_last_route;
-      g_routes[i].next = -1;
-
-      if (g_last_route != -1) {
-       g_routes[g_last_route].next = i;
-      }
-
-      g_last_route = i;
-
-      g_num_routes++;
-      return i;
-    }
-  }
-  return -1;
-}
-
-
-/*
- * This returns an integer, if the interger is negative then AddLink failed, else it was
- * successful and returns the socket descriptor
- */
-
-#if 0
-int AddLink(string input, SOCK * link_sock, string * ret_str) {
-  string output;
-  string hello, password, version, command;
-  string remote_address, type, remote_password;
-  int ctrl_port = 0;
-  int data_port = 0;
-  char buf[128];
-  
-  struct hostent * remote_he;
-  struct in_addr dest_addr;
-  unsigned long dest;
-
-  SOCK data_sock;
-  con_t ctrl_con;
-  int link_index;
-  int ret = CTRL_DO_NOTHING;
-
-  struct sockaddr_in local_address;
-  int local_port;
-
-  *link_sock = 0;
-
-  {
-         istringstream is(input,istringstream::in);
-    is >> hello >> password >> version >> command >> remote_address >> ctrl_port >> data_port >> remote_password >> type;
-  }
-
-
-  if ((remote_address.empty()) || (remote_password.empty()) ||  (type.empty()) || (ctrl_port == 0) || (data_port == 0)) {
-    *ret_str = "Invalid Addlink command";
-    return CTRL_ERROR;
-  }
-
-  if (get_tunnel_type(type) == -1) {
-    *ret_str = "Invalid link type";
-    return CTRL_ERROR;
-  }
-
-  if ((remote_he = gethostbyname(remote_address.c_str())) == NULL) {
-    *ret_str = "Could not lookup address of " + remote_address;
-    return CTRL_ERROR;
-  }
-
-  dest_addr = *((struct in_addr *)remote_he->h_addr);
-  dest = dest_addr.s_addr;
-  
-  link_index = find_link_entry(dest, get_tunnel_type(type));
-
-  if (link_index != -1) {
-    JRLDBG("Link already exists\n");
-    *ret_str = "Link already Exists";
-    return CTRL_ERROR;
-  }
-
-
-  if(type == TCP_STR) {
-    struct sockaddr_in serv_addr;
-
-    if ((data_sock = CreateAndSetupTcpSocket()) < 0) {
-      cerr << "the client descriptor could not be opened" << endl;
-      *ret_str = "Could not establish link";
-      return CTRL_ERROR;
-    }
-    
-    serv_addr.sin_family = AF_INET;
-    serv_addr.sin_port = htons(data_port);
-    serv_addr.sin_addr = dest_addr;
-    memset(&(serv_addr.sin_zero), 0, 8);
-    
-    JRLDBG("Connecting TCP Data link\n");
-    /*we establish a connection with the server */
-    if (connect(data_sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
-      cerr << "the connection could not be established : " << endl;
-      *ret_str = "Could not establish link";
-      return CTRL_ERROR;
-    }
-
-
-    local_port = data_port;
-
-    *ret_str = "Successfully added a TCP link to " + remote_address;
-    ret = CTRL_ADD_TCP_SOCK;
-
-  } else if(type == UDP_STR) {
-    
-    if (GetLocalSockAddress(g_udp_sockfd, (struct sockaddr *)&local_address) == -1) {
-      JRLDBG("Could not get local address\n");
-      return CTRL_ERROR;
-    }
-    local_port = ntohs(local_address.sin_port);
-
-    data_sock = g_udp_sockfd;
-    *ret_str = "Successfully added a virtual UDP link to " + remote_address;
-
-  } 
-
-  *link_sock = data_sock;
-
-  if (create_ctrl_connection(&ctrl_con, remote_address, ctrl_port) == -1) {
-    JRLDBG("Could not establish control connection\n");
-    *ret_str = "Could not register new link";
-    if (type == TCP_STR) {
-      CLOSE_SSL(use_ssl_data, ssl);
-      CLOSE(*link_sock);
-    }
-    return CTRL_ERROR;
-  }
-
-  JRLDBG("ctrl session established\n");
-
-  snprintf(buf, 128, "%s %d", "myself", local_port);
-  output = "REGISTERLINK ";
-  output = output + buf + " " + type;
-
-  if (send_ctrl_msg(ctrl_con, output, remote_password) == -1) {
-    JRLDBG("Could not send the control message\n");
-    *ret_str = "Could not register new link";
-    if (type == TCP_STR) {
-      CLOSE_SSL(use_ssl_data, ssl);
-      CLOSE(*link_sock);
-    }
-    return CTRL_ERROR;
-  }
-
-  JRLDBG("Ctrl message sent\n");
-  if (close_ctrl_connection(ctrl_con, remote_password) == -1) {
-    JRLDBG("Could not close control connection\n");
-  }
-
-  link_index = add_link_entry(dest, get_tunnel_type(type), LINK, data_port, 1, data_sock);
-  
-  if (link_index == -1) {
-    *ret_str = "Could not add link entry";
-    if (type == TCP_STR) {
-      CLOSE_SSL(use_ssl_data, ssl);
-      CLOSE(*link_sock);
-    }
-    return CTRL_ERROR;
-  }
-
-  JRLDBG("Addlink Created link: FD=%d\n", g_links[link_index].link_sock);
-
-  return ret;
-}
-
-
-
-int AddRoute(string input, string * ret_str) {
-  int src_mac_qual;
-  int dest_mac_qual;
-
-  int dest;
-  int src;
-
-  int route_index;
-
-  int route_type;
-  int src_route_type;
-
-  char src_mac[6];
-  char dest_mac[6];
-
-  string hello, version, password, command;
-  string src_str, dest_str, src_mac_str, dest_mac_str, src_type, type;
-  
-
-  {
-    istringstream is(input,istringstream::in);
-    is >> hello >> password >> version >> command >> src_mac_str >> dest_mac_str >>  type >> dest_str >> src_type >> src_str;
-  }
-
-  if ((src_mac_str.empty()) || (dest_mac_str.empty()) || 
-      (dest_str.empty()) || (type.empty())) {
-    *ret_str = "Invalid AddRoute command";
-    return CTRL_ERROR;
-  }
+          if ((dest_mac_qual != ANY_TYPE) && (dest_mac_qual != NONE_TYPE)) {
+               memcpy(g_routes[i].dest_mac, dest_mac, 6);
+          } else {
+               memset(g_routes[i].dest_mac, 0, 6);
+          }
 
+           g_routes[i].src_mac_qual = src_mac_qual;
+           g_routes[i].dest_mac_qual = dest_mac_qual;
+           g_routes[i].dest = dest;
+           g_routes[i].type = type;
+           g_routes[i].src = src;
+           g_routes[i].src_type = src_type;
+           g_routes[i].use = 1;
 
-  if (get_route_type(type) == -1) {
-    *ret_str = "Invalid route type";
-    return CTRL_ERROR;
-  }
+           if (g_first_route == -1) 
+                g_first_route = i;
 
+           g_routes[i].prev = g_last_route;
+           g_routes[i].next = -1;
 
-  if (!(src_type.empty()) && (get_route_src_type(src_type) == -1)) {
-    *ret_str = "Invalid route source type";
-    return CTRL_ERROR;
-  }
+           if (g_last_route != -1) {
+               g_routes[g_last_route].next = i;
+           }
 
+           g_last_route = i;
 
-  //We will first do some parsing to obtain correct the qualifier for source and destination address
-  if (src_mac_str.find(":",0) == string::npos) {
-    src_mac_qual = get_qual_type(src_mac_str);
+           g_num_routes++;
 
-    if (src_mac_qual == -1) {
-      *ret_str = "Invalid Qual Type";
-      return CTRL_ERROR;
+            return i;
     }
-
-    memset(src_mac, 0, 6);
-  } else {
-    if(src_mac_str.substr(0,3) == NOT) {
-      src_mac_qual = NOT_TYPE;
-      src_mac_str = src_mac_str.substr(4);
-    } else {
-      src_mac_qual = EMPTY_TYPE;
-    }
-    
-    src_mac_str = src_mac_str.substr(0,2) + src_mac_str.substr(3,2) + src_mac_str.substr(6,2) + src_mac_str.substr(9,2) + src_mac_str.substr(12,2) + src_mac_str.substr(15,2);
-  
-    ConvertHexEthernetAddressToBinary(src_mac_str.c_str(), src_mac);
   }
-  
-
-  if (dest_mac_str.find (":",0) == string::npos) {
-    dest_mac_qual = get_qual_type(dest_mac_str);
 
-    if (dest_mac_qual == -1) {
-         ret_str->assign("Invalid Qual Type");
-      return CTRL_ERROR;
-    }
-
-    memset(dest_mac, 0, 6);
-  } else {
-    if(dest_mac_str.substr(0,3) == NOT) {
-      dest_mac_qual = NOT_TYPE;
-      dest_mac_str = dest_mac_str.substr(4);
-    } else {
-      dest_mac_qual = EMPTY_TYPE;
-    }
-    
-    dest_mac_str = dest_mac_str.substr(0,2) + dest_mac_str.substr(3,2) + dest_mac_str.substr(6,2) + dest_mac_str.substr(9,2) + dest_mac_str.substr(12,2) + dest_mac_str.substr(15,2);
-    
-    ConvertHexEthernetAddressToBinary(dest_mac_str.c_str(), dest_mac);  
-  }
+  clear_hash_cache();
   
-  if (type == INTERFACE) {
-    int dest_dev;
-    
-    dest_dev = get_device(dest_str);
-
-    if (dest_dev == -1) {
-         ret_str->assign("Could not find Destination Interface");
-      return CTRL_ERROR;
-    }
-
-    dest = dest_dev;
-    
-    route_type = INTERFACE_TYPE;
-  } else if (type == EDGE) {
-    hostent * remote_he;
-
-    if ((remote_he = gethostbyname(dest_str.c_str())) == NULL) {
-      ret_str->assign("Could not lookup address for " + dest_str);
-      return CTRL_ERROR;
-    }
-
-    dest = find_link_entry((*((struct in_addr *)remote_he->h_addr)).s_addr, -1);
-    if (dest == -1) {
-      JRLDBG("AddRoute: Invalid Destination: %s\n", inet_ntoa((*((struct in_addr *)remote_he->h_addr))));
-      ret_str->assign("Addroute requested for invalid destination");
-      return CTRL_ERROR;
-    }
-     
-    route_type = EDGE_TYPE;
-  } 
-
-
-  if (src_type.empty() || (src_type == ANY_SRC)) {
-    src = -1;
-    src_route_type = ANY_SRC_TYPE;
-  } else if (src_type == INTERFACE) {
-
-    if (src_str.empty()) {
-               ret_str->assign("Missing Source INTERFACE");
-      return CTRL_ERROR;
-    }
-
-    if (src_str == ANY_SRC) {
-      src = -1;
-    } else {
-      int src_dev;
-      src_dev = get_device(src_str);
-      
-      if (src_dev == -1) {
-                 ret_str->assign("Could not find Source Interface");
-       return CTRL_ERROR;
-      }
-      
-      src = src_dev;
-    }
-    src_route_type = INTERFACE_TYPE;
-
-  } else if (src_type == EDGE) {
-
-    if (src_str == ANY_SRC) {
-      src = -1;
-    } else {
-      hostent * src_he;
-
-      if (src_str.empty()) {
-                 ret_str->assign("Missing Source EDGE Address");
-       return CTRL_ERROR;
-      }
-      
-      if ((src_he = gethostbyname(src_str.c_str())) == NULL) {
-                 ret_str->assign("Could not lookup address for " + src_str);
-       return CTRL_ERROR;
-      }
-
-      src = find_link_entry((*((struct in_addr *)src_he->h_addr)).s_addr, -1);
-  
-      if (src == -1) {
-       JRLDBG("AddRoute: Invalid Destination: %s\n", inet_ntoa((*((struct in_addr *)src_he->h_addr))));
-               ret_str->assign("Addroute requested for invalid destination");
-       return CTRL_ERROR;
-      }
-    }
-
-    src_route_type = EDGE_TYPE;
-
-  }
-
-
-  JRLDBG("Route Def: %d:%d:%d:%d:%d:%d  %d:%d:%d:%d:%d:%d src_qual=%d, dest_qual=%d, dest=%d, type=%d src=%d, src_type=%d\n",  src_mac[0], src_mac[1], src_mac[2], src_mac[3], src_mac[4], src_mac[5], dest_mac[0], dest_mac[1], dest_mac[2], dest_mac[3], dest_mac[4], dest_mac[5], src_mac_qual, dest_mac_qual, dest, route_type, src, src_route_type);
-
-  route_index = find_route_entry(src_mac, dest_mac, src_mac_qual, dest_mac_qual, dest, route_type, src, src_route_type);
-
-  if (route_index != -1) {
-    JRLDBG("Route Already Exists, Index: %d\n", route_index);
-       ret_str->assign("Route alredy Exists");
-    return CTRL_ERROR;
-  }
-
-  route_index = add_route_entry(src_mac, dest_mac, src_mac_qual, dest_mac_qual, dest, get_route_type(type), src, src_route_type);
-    
-  if (route_index >= 0) {
-         ret_str->assign("Successfully added the route for " +src_mac_str+ " and "+dest_mac_str);
-  } else {
-         ret_str->assign("Could not add route for " + src_mac_str + " and " + dest_mac_str);
-    return CTRL_ERROR;
-  }
-
-  return route_index;  
-}
-
-#endif
-
-int add_device_to_table(char *device_name, int type) {
-  int i;
-
-  for (i = 0; i < MAX_DEVICES; i++) {
-    if (g_devices[i].use == 0) {
- //     g_devices[i].device_name = device_name;
-      strcpy(g_devices[i].device_name, device_name);
-      g_devices[i].type = type;
-      g_devices[i].use = 1;
-
-      if (g_first_device == -1) 
-       g_first_device = i;
-
-      g_devices[i].prev = g_last_device;
-      g_devices[i].next = -1;
-
-      if (g_last_device != -1) 
-       g_devices[g_last_device].next = i;
-
-      g_last_device = i;
-
-      g_num_devices++;
-      return i;
-    }
-  }
   return -1;
 }
 
 
-int find_link_entry(unsigned long dest, int type) {
+static int find_link_entry(unsigned long dest, int type) 
+{
   int i;
 
-  //  PringDebug("Src: %lu, Dst: %lu\n", src, dest);
-
   FOREACH_LINK(i, g_links, g_first_link) {
-    if ( (g_links[i].dest == dest) && 
-        ((type == -1) || (g_links[i].type == type)) ) {
-      return i;
-    }
+      if ((g_links[i].dest == dest) && 
+           ((type == -1) || (g_links[i].type == type)) ) {
+          return i;
+      }
   } 
 
   return -1;
 }
 
-int delete_link_entry(int index) {
+static int delete_link_entry(int index) 
+{
   int next_i;
   int prev_i;
 
@@ -1148,7 +511,6 @@ int delete_link_entry(int index) {
   }
 
   g_links[index].dest = 0;
-//  g_links[index].authenticated = 0;
   g_links[index].type = 0;
   g_links[index].link_sock = -1;
   g_links[index].use = 0;
@@ -1159,7 +521,6 @@ int delete_link_entry(int index) {
   if (prev_i != -1)
     g_links[prev_i].next = g_links[index].next;
 
-
   if (next_i != -1) 
     g_links[next_i].prev = g_links[index].prev;
 
@@ -1177,97 +538,62 @@ int delete_link_entry(int index) {
   return 0;
 }
 
-int delete_link_entry_by_addr(unsigned long dest, int type) {
+int vnet_delete_link_entry_by_addr(unsigned long dest, int type) 
+{
   int index = find_link_entry(dest, type);
   
   if (index == -1) {
-    return -1;
+       return -1;
   }
 
   return delete_link_entry(index);
 }
 
-#if 0
-int delete_device(string device_name) {
-  int index = get_device(device_name);
-  
-  if (index == -1) {
-    return -1;
-  }
-
-  delete_device(index);
-
-  return 0;
-}
-
-#endif
-
-int delete_device(int index) {
-  int next_i;
-  int prev_i;
-
-  g_devices[index].device_name = "";
-  g_devices[index].use = 0;
-
-
-  prev_i = g_devices[index].prev;
-  next_i = g_devices[index].next;
-
-  if (prev_i != -1)
-    g_devices[prev_i].next = g_devices[index].next;
-
-
-  if (next_i != -1) 
-    g_devices[next_i].prev = g_devices[index].prev;
-
-  if (g_first_device == index)
-    g_first_device = g_devices[index].next;
-
-  if (g_last_device == index) 
-    g_last_device = g_devices[index].prev;
 
-  g_devices[index].next = -1;
-  g_devices[index].prev = -1;
-
-  g_num_devices--;
-
-  return 0;
-}
-
-int find_route_entry(char src_mac[6], char dest_mac[6], int src_mac_qual, int dest_mac_qual, int dest, int type, int src, int src_type) {
+static int find_route_entry(char src_mac[6], 
+                                                       char dest_mac[6], 
+                                                       int src_mac_qual, 
+                                                       int dest_mac_qual, 
+                                                       int dest, 
+                                                       int type, 
+                                                       int src, 
+                                                       int src_type) 
+{
   int i;
   char temp_src_mac[6];
   char temp_dest_mac[6];
   
   if ((src_mac_qual != ANY_TYPE) && (src_mac_qual != NONE_TYPE)) {
-    memcpy(temp_src_mac, src_mac, 6);
+      memcpy(temp_src_mac, src_mac, 6);
   } else {
-    memset(temp_src_mac, 0, 6);
+      memset(temp_src_mac, 0, 6);
   }
   
   if ((dest_mac_qual != ANY_TYPE) && (dest_mac_qual != NONE_TYPE)) {
-    memcpy(temp_dest_mac, dest_mac, 6);
+      memcpy(temp_dest_mac, dest_mac, 6);
   } else {
-    memset(temp_dest_mac, 0, 6);
+      memset(temp_dest_mac, 0, 6);
   }
 
   FOREACH_LINK(i, g_routes, g_first_route) {
-    if ( (memcmp(temp_src_mac, g_routes[i].src_mac, 6) == 0) && 
-        (memcmp(temp_dest_mac, g_routes[i].dest_mac, 6) == 0) &&
-        (g_routes[i].src_mac_qual == src_mac_qual) &&
-        (g_routes[i].dest_mac_qual == dest_mac_qual)  &&
-        ( (type == -1) || 
-          ((type == g_routes[i].type) && (g_routes[i].dest == dest))) &&
-        ( (src_type == -1) || 
-          ((src_type == g_routes[i].src_type) && (g_routes[i].src == src))) ) {
-      return i;
-    }
+      if ((memcmp(temp_src_mac, g_routes[i].src_mac, 6) == 0) && 
+           (memcmp(temp_dest_mac, g_routes[i].dest_mac, 6) == 0) &&
+           (g_routes[i].src_mac_qual == src_mac_qual) &&
+           (g_routes[i].dest_mac_qual == dest_mac_qual)  &&
+           ((type == -1) || 
+           ((type == g_routes[i].type) && (g_routes[i].dest == dest))) &&
+           ((src_type == -1) || 
+           ((src_type == g_routes[i].src_type) && (g_routes[i].src == src))) ) 
+      {
+          return i;
+      }
   } 
 
   return -1;
 }
 
-int delete_route_entry(int index) {
+static int delete_route_entry(int index) 
+{
   
   int next_i;
   int prev_i;
@@ -1282,7 +608,6 @@ int delete_route_entry(int index) {
   g_routes[index].type = -1;
   g_routes[index].src_type = -1;
   g_routes[index].use = 0;
-  
 
   prev_i = g_routes[index].prev;
   next_i = g_routes[index].next;
@@ -1290,7 +615,6 @@ int delete_route_entry(int index) {
   if (prev_i != -1)
     g_routes[prev_i].next = g_routes[index].next;
 
-
   if (next_i != -1) 
     g_routes[next_i].prev = g_routes[index].prev;
 
@@ -1305,14 +629,25 @@ int delete_route_entry(int index) {
 
   g_num_routes--;
 
+  clear_hash_cache();
+
   return 0;
 }
 
-int delete_route_entry_by_addr(char src_mac[6], char dest_mac[6], int src_mac_qual, int dest_mac_qual, int dest, int type, int src, int src_type) {
-  int index = find_route_entry(src_mac, dest_mac, src_mac_qual, dest_mac_qual, dest, type, src, src_type);
+int vnet_delete_route_entry_by_addr(char src_mac[6], 
+                                                                               char dest_mac[6], 
+                                                                               int src_mac_qual, 
+                                                                               int dest_mac_qual, 
+                                                                               int dest, 
+                                                                               int type, 
+                                                                               int src, 
+                                                                               int src_type) 
+{
+  int index = find_route_entry(src_mac, dest_mac, src_mac_qual, 
+                                                       dest_mac_qual, dest, type, src, src_type);
   
   if (index == -1) {
-    return -1;
+      return -1;
   }
 
   delete_route_entry(index);
@@ -1320,297 +655,6 @@ int delete_route_entry_by_addr(char src_mac[6], char dest_mac[6], int src_mac_qu
   return 0;
 }
 
-
-#if 0
-int DeleteLink(string input, SOCK * link_sock, string * ret_str) {
-  string output;
-  string hello,password, version, command;
-  string remote_address, type, remote_password;
-  int ctrl_port = 0;
-
-  struct hostent * remote_he;
-  unsigned long dest_addr;
-
-  int link_index;
-  int ret = CTRL_DO_NOTHING;
-
-  con_t ctrl_con;
-  struct sockaddr_in local_address;
-  char buf[128];
-
-  *link_sock = 0;
-
-  {
-    istringstream is(input,istringstream::in);
-    is >> hello >> password >> version >> command >> remote_address >> ctrl_port >> remote_password >> type ;
-  }
-
-  if ((remote_address.empty()) || (remote_password.empty()) || 
-      (type.empty()) || (ctrl_port == 0)) {
-    *ret_str = "Invalid Deletelink command";
-    return CTRL_ERROR;
-  }
-
-  if (get_tunnel_type(type) == -1) {
-    *ret_str = "Invalid link type";
-    return CTRL_ERROR;
-  }
-
-  if ((remote_he = gethostbyname(remote_address.c_str())) == NULL) {
-    *ret_str = "could not lookup address of " + remote_address;
-    return CTRL_ERROR;
-  }
-
-  dest_addr = (*((struct in_addr *)remote_he->h_addr)).s_addr; 
-
-  JRLDBG("Deleting  Dst: %lu\n", dest_addr);
-
-  link_index = find_link_entry(dest_addr, get_tunnel_type(type));
-
-
-  if (link_index == -1) {
-    JRLDBG("Link Does Not Exist\n");
-    *ret_str = "Link Does not exist";
-    return CTRL_ERROR;
-  }
-
-  if (type == TCP_STR) {
-    *link_sock = g_links[link_index].link_sock;
-    *ret_str = "Successfully deleted a TCP link to " + remote_address;
-    ret = CTRL_DELETE_TCP_SOCK;
-
-  } else if (type == UDP_STR) {
-    *ret_str = "Successfully deleted a virtual UDP link to " + remote_address;
-  } else if (type == VTP_STR) {
-    *ret_str = "Successfully deleted a VTP link to " + remote_address;
-    // TODO: Send delete control message
-  }
-
-
-
-  if (create_ctrl_connection(&ctrl_con, remote_address, ctrl_port) == -1) {
-    JRLDBG("Could not establish control connection\n");
-    *ret_str = "Could not deregister link";
-    CLOSE(*link_sock);
-    return CTRL_ERROR;
-  }
-
-
-  /*
-    if (GetLocalSockAddress(ctrl_con.sock, (struct sockaddr *)&local_address) == -1) {
-    JRLDBG("Could not get local address\n");
-    *ret_str = "Could not deregister link";
-    CLOSE(*link_sock);
-    return CTRL_ERROR;
-    }
-    
-    snprintf(buf, 128, "%s", inet_ntoa(local_address.sin_addr));
-  */
-  output = "DEREGISTERLINK ";
-  output = output + "myself" + " " + type;
-
-  if (send_ctrl_msg(ctrl_con, output, remote_password) == -1) {
-    // Could not register on the remote host, 
-    CLOSE(*link_sock);
-    *ret_str = "Could not deregister link on remote host";
-    return CTRL_ERROR;
-  }
-
-  if (close_ctrl_connection(ctrl_con, remote_password) == -1) {
-    JRLDBG("Could not close control connection\n");
-  }
-
-  if (close_link(link_index) == -1) {
-    *ret_str = "Could not delete link";
-    return CTRL_ERROR;
-  }
-
-  return ret;
-}
-
-
-int DeleteRoute(string input, string * ret_str) {
-  int src_mac_qual;
-  int dest_mac_qual;
-
-  int dest;
-  int src;
-
-  int ret = 0;
-  char src_mac[6];
-  char dest_mac[6];
-
-  int route_type;
-  int src_route_type;
-
-  string hello, version, password, command;
-  string src_str, dest_str, src_mac_str, dest_mac_str, type, src_type;
-  
-  {
-    istringstream is(input,istringstream::in);
-    is >> hello >> password >> version >> command >> src_mac_str >> dest_mac_str >> type >> dest_str >> src_type >> src_str ;
-  }
-
-  if ((src_mac_str.empty()) || (dest_mac_str.empty()) || 
-      (dest_str.empty()) || (type.empty())) {
-                 ret_str->assign("Invalid Deleteroute command");
-    return CTRL_ERROR;
-  }
-
-
-  if (get_route_type(type) == -1) {
-         ret_str->assign("Invalid route type");
-    return CTRL_ERROR;
-  }
-
-  if (!(src_type.empty()) && (get_route_src_type(src_type) == -1)) {
-    ret_str->assign("Invalid route source type");
-    return CTRL_ERROR;
-  }
-
-  //We will first do some parsing to obtain correct the qualifier for source and destination address
-  if (src_mac_str.find(":",0) == string::npos) {
-    src_mac_qual = get_qual_type(src_mac_str);
-
-    if (src_mac_qual == -1) {
-      ret_str->assign("Invalid qual type");
-      return CTRL_ERROR;
-    }
-
-    memset(src_mac, 0, 6);
-  } else {
-    if(src_mac_str.substr(0,3) == NOT) {
-      src_mac_qual = NOT_TYPE;
-      src_mac_str = src_mac_str.substr(4);
-    } else {
-      src_mac_qual = EMPTY_TYPE;
-    }
-    
-    src_mac_str = src_mac_str.substr(0,2) + src_mac_str.substr(3,2) + src_mac_str.substr(6,2) + src_mac_str.substr(9,2) + src_mac_str.substr(12,2) + src_mac_str.substr(15,2);
-  
-    ConvertHexEthernetAddressToBinary(src_mac_str.c_str(), src_mac);
-  }
-  
-
-  if (dest_mac_str.find (":",0) == string::npos) {
-    dest_mac_qual = get_qual_type(dest_mac_str);
-
-    if (dest_mac_qual == -1) {
-               ret_str->assign("Invalid Qual Type");
-      return CTRL_ERROR;
-    }
-
-    memset(dest_mac, 0, 6);
-  } else {
-    if(dest_mac_str.substr(0,3) == NOT) {
-      dest_mac_qual = NOT_TYPE;
-      dest_mac_str = dest_mac_str.substr(4);
-    } else {
-      dest_mac_qual = EMPTY_TYPE;
-    }
-    
-    dest_mac_str = dest_mac_str.substr(0,2) + dest_mac_str.substr(3,2) + dest_mac_str.substr(6,2) + dest_mac_str.substr(9,2) + dest_mac_str.substr(12,2) + dest_mac_str.substr(15,2);
-    
-    ConvertHexEthernetAddressToBinary(dest_mac_str.c_str(), dest_mac);  
-  }
-  
-  if (type == INTERFACE) {
-    int dest_dev;
-
-    dest_dev = get_device(dest_str);
-
-    if (dest_dev == -1) {
-               ret_str->assign("Could not find Destination Interface");
-      return CTRL_ERROR;
-    }
-
-    dest = dest_dev;
-
-    route_type = INTERFACE_TYPE;
-  } else if (type == EDGE) {
-    hostent * remote_he;
-
-    if ((remote_he = gethostbyname(dest_str.c_str())) == NULL) {
-               ret_str->assign("Could not lookup address for " + dest_str);
-      return CTRL_ERROR;
-    }
-
-    dest = find_link_entry((*((struct in_addr *)remote_he->h_addr)).s_addr, -1);
-    if (dest == -1) {
-               ret_str->assign("Route requested for invalid destination");
-      return CTRL_ERROR;
-    }
-
-    route_type = EDGE_TYPE;
-  }
-
-
-  if (src_type.empty() || (src_type == ANY_SRC)) {
-    src = -1;
-    src_route_type = ANY_SRC_TYPE;
-  } else if (src_type == INTERFACE) {
-
-    if (src_str.empty()) {
-               ret_str->assign("Missing Source INTERFACE");
-      return CTRL_ERROR;
-    }
-    if (src_str == ANY_SRC) {
-      src = -1;
-    } else {
-      int src_dev;
-      src_dev = get_device(src_str);
-      
-      if (src_dev == -1) {
-                 ret_str->assign("Could not find Source Interface");
-       return CTRL_ERROR;
-      }
-      
-      src = src_dev;
-    }
-    src_route_type = INTERFACE_TYPE;
-
-  } else if (src_type == EDGE) {
-
-    if (src_str.empty()) {
-               ret_str->assign("Missing Source EDGE Address");
-      return CTRL_ERROR;
-    }
-
-    if (src_str == ANY_SRC) {
-      src = -1;
-    } else {
-      hostent * src_he;
-    
-      if ((src_he = gethostbyname(src_str.c_str())) == NULL) {
-                 ret_str->assign("Could not lookup address for " + src_str);
-       return CTRL_ERROR;
-      }
-      
-      src = find_link_entry((*((struct in_addr *)src_he->h_addr)).s_addr, -1);
-
-      if (src == -1) {
-       JRLDBG("DeleteRoute: Invalid Destination: %s\n", inet_ntoa((*((struct in_addr *)src_he->h_addr))));
-               ret_str->assign("DeleteToute requested for invalid destination");
-       return CTRL_ERROR;
-      }
-    }
-    src_route_type = EDGE_TYPE;
-  }
-
-  ret = delete_route_entry(src_mac, dest_mac, src_mac_qual, dest_mac_qual, dest, route_type, src, src_route_type);
-  
-  if (ret == 0) {
-         ret_str->assign("Successfully deleted the route for " +src_mac_str+ " and "+dest_mac_str);
-  } else {
-         ret_str->assign("Could not delete the route");
-    return CTRL_ERROR;
-  }
-  
-  return ret;
-}
-#endif
-
 int delete_sock(struct sock_list * socks, int *first_sock, int *last_sock, SOCK fd) {
   int i;
   int prev_i;
@@ -1646,528 +690,434 @@ int delete_sock(struct sock_list * socks, int *first_sock, int *last_sock, SOCK
   return -1;
 }
 
-/*
-//During testing, route table, link table, etc. are writen in program, isteadjing of AddRoute(), AddLink()...
-void Create_topologies()
-{
-       //create link table
-       unsigned long dest; //  dest_addr = *((struct in_addr *)remote_he->h_addr);  dest = dest_addr.s_addr;
-       add_link_entry(dest, TCP_STR, int data_port, SOCK fd)  //the parameter need modify
-
-       //create device table
-
-       add_device_to_table(eth0)
-
-       //create route table
-       //example(VnetClientJava):FORWARD endeavor.cs.northwestern.edu EDGE not-00:0C:29:0F:4E:AA 00:0C:29:0F:4E:AA virtuoso-22.cs.northwestern.edu ANY ANY     
-       //format(VnetClientJava): String routeStr = "FORWARD " + host.getHostname() + " " + dstType +  " " +  srcMacStr + " " + dstMacStr + " " + dst + " " + srcType + " " + src; 
-       char src_mac[6]; //={};  //00:0C:29:0F:4E:AA
-       char dest_mac[6];       //00:0C:29:0F:4E:AA, empty type is only a mac adress.
-       add_route_entry(src_mac, dest_mac, NOT_TYPE, EMPTY_TYPE, , EDGE, ANY, ANY); //decide "dest" after creade device table or link table.
-}
-
-*/
-
-
-//int data_port, is udp/tcp port.  SOCK fd comes from socket() function.. so this function is called after socket().
-void store_topologies(int data_port,  SOCK fd)
+//setup the topology of the testing network
+static void store_topologies(SOCK fd)
 {
        int i;
        int src_mac_qual = ANY_TYPE;
        int dest_mac_qual = ANY_TYPE;
-       int dest =0; //this is in_addr.s_addr
+       uint_t dest;
+#ifndef VNET_SERVER
+       dest = (0 | 172 << 24 | 23 << 16 | 1 ); //this is in_addr.s_addr
+       PrintDebug("VNET: store_topologies. NO VNET_SERVER, dest = %x\n", dest);
+#elif
+       dest = (0 | 172 << 24 | 23 << 16 | 2 ); //this is in_addr.s_addr
+       PrintDebug("VNET: store_topologies. VNET_SERVER, dest = %x\n", dest);
+#endif
+
        int type = UDP_TYPE;
        int src = 0;
        int src_type= ANY_SRC_TYPE;
+       int data_port = 22;
        
        //store link table
-  for(i = 0; i < 1; i++) {
-    if (g_links[i].use == 0) {
-      g_links[i].dest = dest;
- //     g_links[i].authenticated = authenticated;
-      g_links[i].type = type;
-      g_links[i].link_sock = fd;
-      g_links[i].remote_port = data_port;
-      g_links[i].use = 1;
- //     g_links[i].link_class = link_class;
-
-      if (g_first_link == -1) 
-       g_first_link = i;
-
-      g_links[i].prev = g_last_link;
-      g_links[i].next = -1;
+      for(i = 0; i < MAX_LINKS; i++) {
+          if (g_links[i].use == 0) {
+               g_links[i].dest = (int)dest;
+               g_links[i].type = type;
+               g_links[i].link_sock = fd;
+               g_links[i].remote_port = data_port;
+               g_links[i].use = 1;
+
+               if (g_first_link == -1) 
+                    g_first_link = i;
+
+               g_links[i].prev = g_last_link;
+               g_links[i].next = -1;
       
-      if (g_last_link != -1) {
-       g_links[g_last_link].next = i;
-      }
+               if (g_last_link != -1) {
+                    g_links[g_last_link].next = i;
+               }
 
-      g_last_link = i;
+               g_last_link = i;
 
-      g_num_links++;
-    }
-  }
+               g_num_links++;
+               PrintDebug("VNET: store_topologies. new link: socket: %d, remote %x:[%d]\n", g_links[i].link_sock, (uint_t)g_links[i].dest, g_links[i].remote_port);
+         }
+      }
+
+  
        //store route table
 
        type = EDGE_TYPE;
        dest =0;
 
-       for(i = 0; i < 1; i++) {
+       for(i = 0; i < MAX_ROUTES; i++) {
                if (g_routes[i].use == 0) {
-     
-                if ((src_mac_qual != ANY_TYPE) && (src_mac_qual != NONE_TYPE)) {
-       //              memcpy(g_routes[i].src_mac, src_mac, 6);
-               } else {
+                 if ((src_mac_qual != ANY_TYPE) && (src_mac_qual != NONE_TYPE)) {
+       //                  memcpy(g_routes[i].src_mac, src_mac, 6);
+                   } else {
                        memset(g_routes[i].src_mac, 0, 6);
-               }
+                   }
       
-               if ((dest_mac_qual != ANY_TYPE) && (dest_mac_qual != NONE_TYPE)) {
-       //              memcpy(g_routes[i].dest_mac, dest_mac, 6);
-               } else {
-                       memset(g_routes[i].dest_mac, 0, 6);
-               }
-
-      g_routes[i].src_mac_qual = src_mac_qual;
-      g_routes[i].dest_mac_qual = dest_mac_qual;
-      g_routes[i].dest = dest;
-      g_routes[i].type = type;
-      g_routes[i].src = src;
-      g_routes[i].src_type = src_type;
-      
-      g_routes[i].use = 1;
-
-      if (g_first_route == -1) 
-               g_first_route = i;
-
-      g_routes[i].prev = g_last_route;
-      g_routes[i].next = -1;
+                   if ((dest_mac_qual != ANY_TYPE) && (dest_mac_qual != NONE_TYPE)) {
+       //                  memcpy(g_routes[i].dest_mac, dest_mac, 6);
+                   } else {
+                          memset(g_routes[i].dest_mac, 0, 6);
+                   }
+
+             g_routes[i].src_mac_qual = src_mac_qual;
+             g_routes[i].dest_mac_qual = dest_mac_qual;
+             g_routes[i].dest = (int)dest;
+             g_routes[i].type = type;
+             g_routes[i].src = src;
+             g_routes[i].src_type = src_type;
+             
+             g_routes[i].use = 1;
+
+             if (g_first_route == -1) 
+                       g_first_route = i;
+
+             g_routes[i].prev = g_last_route;
+             g_routes[i].next = -1;
+
+             if (g_last_route != -1) {
+               g_routes[g_last_route].next = i;
+             }
 
-      if (g_last_route != -1) {
-       g_routes[g_last_route].next = i;
-      }
+             g_last_route = i;
 
-      g_last_route = i;
+             g_num_routes++;
 
-      g_num_routes++;
+               PrintDebug("VNET: store_topologies. new route: src_mac: %s, dest_mac: %s, dest: %d\n", g_routes[i].src_mac, g_routes[i].dest_mac, dest);
 
        }
   }
 }
 
-//int MatchRoute(char * src_mac, char * dst_mac, int src_type, int src_index, int * do_we_analyze, int * matches) {
-int MatchRoute(char * src_mac, char * dst_mac, int src_type, int src_index, int * matches) { 
-
-  int values[g_num_routes];
-  int matched_routes[g_num_routes];
-
-  int num_matches = 0;
-  int i;
-  int max = 0;
-  int no = 0;
-  int exact_match = 0;
-
-
-
-   FOREACH_ROUTE(i, g_routes, g_first_route) {
-    if ( (g_routes[i].src_type != ANY_SRC_TYPE) &&
-     ( (g_routes[i].src_type != src_type) ||
-       ( (g_routes[i].src != src_index) &&
-         (g_routes[i].src != -1) ) ) ) {
-      PrintDebug("Source route is on and does not match\n");
-      continue;
-    }
-
-    if ( (g_routes[i].dest_mac_qual == ANY_TYPE) &&
-     (g_routes[i].src_mac_qual == ANY_TYPE) ) {
-      
-      matched_routes[num_matches] = i;
-      values[num_matches] = 3;
-
-      num_matches++;
-    }
-    
-    if (memcmp((void *)&g_routes[i].src_mac, (void *)src_mac, 6) == 0) {
-      if (g_routes[i].src_mac_qual !=  NOT_TYPE) {
-    if (g_routes[i].dest_mac_qual == ANY_TYPE) {
-      
-      matched_routes[num_matches] = i;
-      values[num_matches] = 6;
-      
-      num_matches++;
-    } else if (memcmp((void *)&g_routes[i].dest_mac, (void *)dst_mac, 6) == 0) {
-      if (g_routes[i].dest_mac_qual != NOT_TYPE) {
-        
-        matched_routes[num_matches] = i;
-        values[num_matches] = 8;
-        
-        exact_match = 1;
-
-        num_matches++;
-      }
-    }
-      }
-    }
-    
-    if (memcmp((void *)&g_routes[i].dest_mac, (void *)dst_mac, 6) == 0) {
-      if (g_routes[i].dest_mac_qual != NOT_TYPE) {
-    if (g_routes[i].src_mac_qual == ANY_TYPE) {
-      
-      matched_routes[num_matches] = i;
-      values[num_matches] = 6;
-
-      num_matches++;
-    } else if (memcmp((void *)&g_routes[i].src_mac, (void *)src_mac, 6) == 0) {
-      if (g_routes[i].src_mac_qual != NOT_TYPE) {
-
-        if (exact_match == 0) {
-          matched_routes[num_matches] = i;
-          values[num_matches] = 8;
-
-          num_matches++;
-        }
-      }
-    }
-      }
-    }
-    
-    if ( (g_routes[i].dest_mac_qual == NOT_TYPE) &&
-     (memcmp((void *)&g_routes[i].dest_mac, (void *)dst_mac, 6) != 0)) {
-      if (g_routes[i].src_mac_qual == ANY_TYPE) {
-    
-    matched_routes[num_matches] = i;
-    values[num_matches] = 5;
-    
-    num_matches++;    
-      } else if (memcmp((void *)&g_routes[i].src_mac, (void *)src_mac, 6) == 0) {
-    if (g_routes[i].src_mac_qual != NOT_TYPE) {
-      
-      matched_routes[num_matches] = i;
-      values[num_matches] = 7;
-      
-      num_matches++;
-    }
-      }
-    }
-    
-    if ( (g_routes[i].src_mac_qual == NOT_TYPE) &&
-     (memcmp((void *)&g_routes[i].src_mac, (void *)src_mac, 6) != 0) ) {
-      if (g_routes[i].dest_mac_qual == ANY_TYPE) {
-    
-    matched_routes[num_matches] = i;
-    values[num_matches] = 5;
-    
-    num_matches++;
-      } else if (memcmp((void *)&g_routes[i].dest_mac, (void *)dst_mac, 6) == 0) {
-    if (g_routes[i].dest_mac_qual != NOT_TYPE) {
-      
-      matched_routes[num_matches] = i;
-      values[num_matches] = 7;
-
-      num_matches++;
-    }
-      }
-    }
-  }
-
+static int match_route(char *src_mac, char *dst_mac, int 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;
+
+    FOREACH_ROUTE(i, g_routes, g_first_route) {
+           if ((g_routes[i].src_type != ANY_SRC_TYPE) &&
+                ((g_routes[i].src_type != src_type) ||
+                ((g_routes[i].src != src_index) &&
+                (g_routes[i].src != -1))))
+           {
+             PrintDebug("Vnet: MatchRoute: Source route is on and does not match\n");
+             continue;
+           }
+
+           if ( (g_routes[i].dest_mac_qual == ANY_TYPE) &&
+            (g_routes[i].src_mac_qual == ANY_TYPE) ) 
+           {      
+              matched_routes[num_matches] = i;
+              values[num_matches] = 3;
+              num_matches++;
+           }
+           
+           if (memcmp((void *)&g_routes[i].src_mac, (void *)src_mac, 6) == 0) 
+           {
+              if (g_routes[i].src_mac_qual !=  NOT_TYPE) {
+                if (g_routes[i].dest_mac_qual == ANY_TYPE) {
+               matched_routes[num_matches] = i;
+               values[num_matches] = 6;
+             
+               num_matches++;
+                  }else if (memcmp((void *)&g_routes[i].dest_mac, (void *)dst_mac, 6) == 0) {
+                       if (g_routes[i].dest_mac_qual != NOT_TYPE) {   
+                               matched_routes[num_matches] = i;
+                               values[num_matches] = 8;    
+                               exact_match = 1;
+                               num_matches++;
+                       }
+                  }
+              }
+           }
+           
+           if (memcmp((void *)&g_routes[i].dest_mac, (void *)dst_mac, 6) == 0) 
+           {
+               if (g_routes[i].dest_mac_qual != NOT_TYPE) {
+                       if (g_routes[i].src_mac_qual == ANY_TYPE) {
+                             matched_routes[num_matches] = i;
+                             values[num_matches] = 6;
+
+                             num_matches++;
+                       } else if (memcmp((void *)&g_routes[i].src_mac, (void *)src_mac, 6) == 0) {
+                               if (g_routes[i].src_mac_qual != NOT_TYPE) {
+                                       if (exact_match == 0) {
+                                         matched_routes[num_matches] = i;
+                                         values[num_matches] = 8;
+                                         num_matches++;
+                                       }
+                               }
+                       }
+             }
+           }
+           
+           if ((g_routes[i].dest_mac_qual == NOT_TYPE) &&
+                 (memcmp((void *)&g_routes[i].dest_mac, (void *)dst_mac, 6) != 0)) 
+           {
+               if (g_routes[i].src_mac_qual == ANY_TYPE) {
+                   matched_routes[num_matches] = i;
+                   values[num_matches] = 5;                
+                   num_matches++;    
+              } else if (memcmp((void *)&g_routes[i].src_mac, (void *)src_mac, 6) == 0) {
+                       if (g_routes[i].src_mac_qual != NOT_TYPE) {      
+                             matched_routes[num_matches] = i;
+                             values[num_matches] = 7;                
+                             num_matches++;
+                       }
+               }
+           }
+           
+           if ((g_routes[i].src_mac_qual == NOT_TYPE) &&
+                (memcmp((void *)&g_routes[i].src_mac, (void *)src_mac, 6) != 0)) 
+           {
+               if (g_routes[i].dest_mac_qual == ANY_TYPE) {
+                   matched_routes[num_matches] = i;
+                   values[num_matches] = 5;        
+                   num_matches++;
+               } else if (memcmp((void *)&g_routes[i].dest_mac, (void *)dst_mac, 6) == 0) {
+                        if (g_routes[i].dest_mac_qual != NOT_TYPE) { 
+                             matched_routes[num_matches] = i;
+                             values[num_matches] = 7;
+                             num_matches++;
+                        }
+             }
+           }
+  }//end FOREACH_ROUTE
 
   FOREACH_ROUTE(i, g_routes, g_first_route) {
-    if ( (memcmp((void *)&g_routes[i].src_mac, (void *)src_mac, 6) == 0) &&
-     (g_routes[i].dest_mac_qual == NONE_TYPE) &&
-     ( (g_routes[i].src_type == ANY_SRC_TYPE) ||
-       ( (g_routes[i].src_type == src_type) &&
-         ( (g_routes[i].src == src_index) ||
-           (g_routes[i].src == -1) )))) {
-
-      matched_routes[num_matches] = i;
-      values[num_matches] = 4;
-      PrintDebug("We matched a default route (%d)\n", i);
-      num_matches++;
-    }
+       if ((memcmp((void *)&g_routes[i].src_mac, (void *)src_mac, 6) == 0) &&
+               (g_routes[i].dest_mac_qual == NONE_TYPE) &&
+               ((g_routes[i].src_type == ANY_SRC_TYPE) ||
+               ((g_routes[i].src_type == src_type) &&
+               ((g_routes[i].src == src_index) ||
+               (g_routes[i].src == -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;
+       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++;
-    }
+       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;
 }
 
-bool HandleDataOverLink(RawEthernetPacket *pkt, int src_link_index)
+static inline int if_write_pkt(struct vnet_if_device *iface, struct raw_ethernet_pkt *pkt)
 {
+   return iface->input((uchar_t *)pkt->data, pkt->size);
+}
 
-  char src_mac[6];
-  char dst_mac[6];
-//  int do_we_analyze;
-
-  int matches[g_num_routes];
+static int handle_one_pkt(struct raw_ethernet_pkt *pkt)
+{
+    int src_link_index = 0;    //the value of src_link_index of udp always is 0
+    int i;
+    char src_mac[6];
+    char dst_mac[6];
 
-  int num_matched_routes = 0;
-  int i;
-  struct HEADERS headers;
-//  char hash_key[HASH_KEY_SIZE];
-
-  // get the ethernet and ip headers from the packet
-  memcpy((void *)&headers, (void *)pkt->data, sizeof(headers));
-  int j;
-  for(j = 0;j < 6; j++) {
-    src_mac[j] = headers.ethernetsrc[j];
-    dst_mac[j] = headers.ethernetdest[j];
-  }
+    int matches[g_num_routes];
+    int num_matched_routes = 0;
 
-//#ifdef DEBUG
-  char dest_str[18];
-  char src_str[18];
+    struct HEADERS headers;
+  
+    // get the ethernet and ip headers from the packet
+    memcpy((void *)&headers, (void *)pkt->data, sizeof(headers));
 
-  mac_to_string(src_mac, src_str);  
-  mac_to_string(dst_mac, dest_str);
+    int j;
+    for(j = 0;j < 6; j++) {
+       src_mac[j] = headers.ethernetsrc[j];
+       dst_mac[j] = headers.ethernetdest[j];
+    }
 
-  PrintDebug("SRC(%s), DEST(%s)\n", src_str, dest_str);
-//#endif
 
-//  make_hash_key(hash_key, src_mac, dst_mac, EDGE_TYPE, src_link_index);
+#ifdef DEBUG
+    char dest_str[18];
+    char src_str[18];
 
+    mac_to_string(src_mac, src_str);  
+    mac_to_string(dst_mac, dest_str);
 
-  //  num_matched_routes = MatchRoute(src_mac, dst_mac, EDGE_TYPE, src_link_index, &do_we_analyze, matches);
-  num_matched_routes = MatchRoute(src_mac, dst_mac, EDGE_TYPE, src_link_index, matches);
+    PrintDebug("Vnet: HandleDataOverLink. SRC(%s), DEST(%s)\n", src_str, dest_str);
+#endif
 
-  PrintDebug("Matches=%d\n", num_matched_routes);
+    char hash_key[HASH_KEY_SIZE];
+    make_hash_key(hash_key, src_mac, dst_mac, EDGE_TYPE, src_link_index);
 
-  for (i = 0; i < num_matched_routes; i++) {
-    int route_index = -1;
-    int link_index = -1;
-    int dev_index = -1;
+    num_matched_routes = look_into_cache((route_hashkey_t)hash_key, matches);
 
-    route_index = matches[i];
+    if (num_matched_routes == -1) {//no match
+        num_matched_routes = match_route(src_mac, dst_mac, pkt->type, src_link_index, matches);
 
-#ifdef DEBUG
-    {
-  //    char *route_str;
-      PrintDebug("Forward packet from link according to Route entry %d\n", route_index);
- //     route_to_str(route_index, &route_str);
-   //   PrintDebug("Route Rule: %s\n", route_str.c_str());
+        if (num_matched_routes > 0)
+            add_route_to_cache(hash_key, num_matched_routes,matches);      
     }
-#endif
 
-    if (g_routes[route_index].type == EDGE_TYPE) {
-     
-      link_index = g_routes[route_index].dest;
-            
-   //   PrintDebug("Destination Host: %s\n", ip_to_string(htonl(g_links[link_index].dest)));
+    PrintDebug("Vnet: HandleDataOverLink: Matches=%d\n", num_matched_routes);
 
-      if(g_links[link_index].type == UDP_TYPE) {
-   
-         int size;
-         PrintDebug("Serializing UDP Packet from LINK, fd=%d\n", g_links[link_index].link_sock);
-         if ((size = V3_SendTo_IP(g_links[link_index].link_sock,  g_links[link_index].dest,  g_links[link_index].remote_port, pkt->data, pkt->size)) != pkt->size)  {
-           PrintError("Vnet: sending by UDP Exception, %x\n", size);
-           return false;
-         }
+    for (i = 0; i < num_matched_routes; i++) {
+        int route_index = -1;
+        int link_index = -1;
+        int dev_index = -1;
 
-      }  else if (g_links[link_index].type == TCP_TYPE) {
- //   PrintDebug("Serializing TCP Packet from link to LINk %s\n", ip_to_string(htonl(g_links[link_index].dest)));
-               RawEthernetPacketSerialize(pkt, g_links[link_index].link_sock);
-      }
-    } else if (g_routes[route_index].type == INTERFACE_TYPE) {
-      dev_index = g_routes[route_index].dest;
-      
-      PrintDebug("Writing Packet to device=%s\n", g_devices[dev_index].device_name);
+        route_index = matches[i];
 
-      if (if_write_pkt(g_devices[dev_index].vnet_device, pkt) == -1) {
-         PrintDebug("Can't write output packet to link\n");
-         return false;
-      }
-    }
-  }
-  return true;
-}
+        PrintDebug("Vnet: HandleDataOverLink: Forward packet from link according to Route entry %d\n", route_index);
 
+        if (g_routes[route_index].type == EDGE_TYPE) {
+            link_index = g_routes[route_index].dest;
 
+            if(g_links[link_index].type == UDP_TYPE) {
+                int size;
 
+                if ((size = V3_SendTo_IP(g_links[link_index].link_sock,  g_links[link_index].dest,  g_links[link_index].remote_port, pkt->data, pkt->size)) != pkt->size)  {
+                    PrintError("Vnet: sending by UDP Exception, %x\n", size);
+                    return -1;
+                }
 
-#endif  //Route
+                PrintDebug("Vnet: HandleDataOverLink: Serializing UDP Packet to link_sock [%d], dest [%x], remote_port [%d], size [%d]\n", g_links[link_index].link_sock, (uint_t)g_links[link_index].dest,  g_links[link_index].remote_port, (int)pkt->size);
 
+            }else if (g_links[link_index].type == TCP_TYPE) {
+            }
+        } else if (g_routes[route_index].type == INTERFACE_TYPE) {
+            dev_index = g_routes[route_index].dest;
+      
+            PrintDebug("Writing Packet to device=%s\n", g_devices[dev_index].device->name);
 
-static void hanlder_ProcessTcp(struct handler *hd)
-{
-  RawEthernetPacket *pt;
-  
-  pt = (RawEthernetPacket *)V3_Malloc(sizeof(RawEthernetPacket));
-  if (pt == NULL){
-       PrintError("Vnet: Malloc fails\n");
-       return;
-  }
+            if (if_write_pkt(g_devices[dev_index].device, pkt) == -1) {
+                 PrintDebug("Can't write output packet to link\n");
+                return -1;
+            }
+        } else {
+            PrintDebug("Vnet: Wrong Edge type\n");
+        }
+    }
 
-  if (RawEthernetPacketUnserialize(pt, hd->fd) == false){
-       PrintError("Vnet: Hanlder:ProcessTcp: receiving packet from TCP fails\n");
-       return;
-  }
+     return 0;
+}
 
-  PrintDebug("Vnet: In Hanlder.ProcessTcp: get packet\n");
-  print_packet(pt->data, pt->size);
-#ifdef ROUTE
-/*  int  *link_index ;
-  link_index = (int *)V3_Malloc(sizeof(int));
-  if (link_index == NULL){
-       PrintError("Vnet: Malloc fails\n");
-       return;
-  }
+static int send_ethernet_pkt(char *buf, int length)
+{
+       struct raw_ethernet_pkt *pt;
 
-  *link_index = find_link_by_fd(hd->fd);
-*/
-  int link_index;
-//  int *link_index_ptr;
-  link_index = find_link_by_fd(hd->fd);
-//  link_index_ptr = &link_index;
-//  v3_enqueue(src_link_index_q, (addr_t)link_index_ptr);
-  pt->index = link_index;
-#endif
-  v3_enqueue(vnet_inpkt_q, (addr_t)pt);
+       pt = (struct raw_ethernet_pkt *)V3_Malloc(sizeof(struct raw_ethernet_pkt));
+       raw_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);
+       return 0;
+       
 }
 
-static void RunUdp(struct handler *hd)
+int V3_Send_pkt(uchar_t *buf, int length)
 {
-  RawEthernetPacket *pt;
+       PrintDebug("VNET: In V3_Send_pkt: pkt length %d\n", length);
 
-  while (1) {
-       pt = (RawEthernetPacket *)V3_Malloc(sizeof(RawEthernetPacket));
-       if (pt == NULL){
-               PrintError("Vnet: Malloc fails\n");
-               return;
-       }
+       return send_ethernet_pkt((char *)buf, length);
+}
 
-       PrintDebug("Vnet: In Hanlder.RunUdp: socket: %d receive from ip %x, port %d\n", hd->fd, hd->remote_address, hd->remote_port);
+static int add_device_to_table(struct vnet_if_device*device, int type) {
+  int i;
 
-       pt->size = V3_RecvFrom_IP(hd->fd, hd->remote_address, hd->remote_port, pt->data, ETHERNET_PACKET_LEN);
+  for (i = 0; i < MAX_DEVICES; i++) {
+      if (g_devices[i].use == 0) {
+          g_devices[i].type = type;
+          g_devices[i].use = 1;
 
-       if (pt->size <= 0){
-               PrintDebug("Vnet: Hanlder:ProcessUdp: receiving packet from UDP fails\n");
-               V3_Free(pt);
-               return;
-       }
+          if (g_first_device == -1) 
+               g_first_device = i;
 
-       PrintDebug("Vnet: In Hanlder.RunUdp: get packet\n");
-       print_packet(pt->data, pt->size);
-       
+          g_devices[i].prev = g_last_device;
+          g_devices[i].next = -1;
 
-       v3_enqueue(vnet_inpkt_q, (addr_t)pt);
-       
-  }
-}
+          if (g_last_device != -1) 
+               g_devices[g_last_device].next = i;
 
+          g_last_device = i;
+          g_num_devices++;
 
-static void RunTcp(struct handler *hd)
-{
-      struct v3_sock_set fds;
-      int rc;
-  
-      while (1) {
-        V3_SOCK_ZERO(&fds);
-        V3_SOCK_SET(hd->fd, &fds);
-        rc = V3_Select_Socket(&fds, NULL, NULL, NULL);
-
-        PrintDebug("Vnet: In Hanlder.Run: Return from Select(): rc : %d\n", rc);
-               
-        if (rc < 0) {
-               PrintError("Vnet: In Hanlder.Run: Return from Select() Error: rc : %d\n", rc);
-               return;
-        } else if (rc == 0) {
-          // huh? didn't ask for timeouts so just repeat
-               continue;
-        } else {
-               hanlder_ProcessTcp(hd);
-        } 
+           return i;
       }
+  }
+  
+  return -1;
 }
 
-static int vnet_handle(struct handler *hd)
-{
-      if (use_tcp)
-               RunTcp(hd);
-      else
-               RunUdp(hd);
-         
-      return 0;
-}
-
-static bool handler_tx_packet(struct handler *hd, RawEthernetPacket *pt)
+static int search_device(char *device_name)
 {
+    int i;
 
-  if (pt == NULL) {
-    PrintError("VNET Hanlder: sending a NULL packet\n");
-       
-    return false;
-  }
-
-  PrintDebug("VNET Hanlder: socket: %d local %x:[%d], remote %x:[%d]\n", hd->fd, hd->local_address, hd->local_port, hd->remote_address, hd->remote_port);
+    for (i=0; i<MAX_DEVICES; i++)
+        if (g_devices[i].use == 1){
+               if (!strcmp(device_name, g_devices[i].device->name))
+                       return i;
+        }
 
-  if (use_tcp)
-       return RawEthernetPacketSerialize(pt, hd->fd);
-  else 
-       return RawEthernetPacketSendUdp(pt, hd->fd, hd->remote_address, hd->remote_port);
+    return -1;
 }
 
-
-int V3_Send_pkt(uchar_t *buf, int length)
+static struct vnet_if_device* delete_device_from_table(int index) 
 {
-       PrintDebug("VNET: In V3_Send_pkt: pkt length %d\n", length);
+    int next_i;
+    int prev_i;
+    struct vnet_if_device *device = NULL;
 
-       print_packet((char *)buf, length);
+    if (g_devices[index].use == 0) 
+         return NULL;
 
-       return vnet_send_pkt((char *)buf, length);
-}
+    g_devices[index].use = 0;
 
-int V3_Register_pkt_event(int (*netif_input)(uchar_t * pkt, uint_t size))
-{
-       return vnet_register_pkt_event("NE2000", netif_input, NULL);
-}
+    prev_i = g_devices[index].prev;
+    next_i = g_devices[index].next;
 
-int vnet_send_pkt(char *buf, int length)
-{
-       struct handler * hd;
-       RawEthernetPacket pt;
+    if (prev_i != -1)
+        g_devices[prev_i].next = g_devices[index].next;
 
-       hd = get_handler();
+    if (next_i != -1) 
+        g_devices[next_i].prev = g_devices[index].prev;
 
-       if (hd == NULL){
-               return -1;
-       }
+    if (g_first_device == index)
+        g_first_device = g_devices[index].next;
 
-       PrintDebug("Vnet: vnet_send_pkt: get handler: %p\n", hd);
+    if (g_last_device == index) 
+        g_last_device = g_devices[index].prev;
 
-       RawEthernetPacketInit(&pt, buf, length);  //====here we copy sending data once 
+    g_devices[index].next = -1;
+    g_devices[index].prev = -1;
 
-       if (!handler_tx_packet(hd, &pt))
-               return -1;
+    device = g_devices[index].device;
+    g_devices[index].device = NULL;
 
-       V3_Yield();
+    g_num_devices--;
 
-       return 0;
-       
+    return device;
 }
 
-int vnet_register_pkt_event(char *dev_name, int (*netif_input)(uchar_t * pkt, uint_t size), void *data)
+
+int vnet_register_device(char *dev_name, int (*netif_input)(uchar_t * pkt, uint_t size), void *data)
 {
-       struct vnet_device *dev;
+       struct vnet_if_device *dev;
 
-       dev = (struct vnet_device *)V3_Malloc(sizeof(struct vnet_device));
+       dev = (struct vnet_if_device *)V3_Malloc(sizeof(struct vnet_if_device));
 
        if(dev == NULL){
                PrintError("VNET: Malloc fails\n");
@@ -2175,295 +1125,212 @@ int vnet_register_pkt_event(char *dev_name, int (*netif_input)(uchar_t * pkt, ui
        }
 
        strncpy(dev->name, dev_name, (strlen(dev_name) < 50)?strlen(dev_name):50);
-
        dev->input = netif_input;
        dev->data = data;
 
-       if (!add_device(dev))
+       if (add_device_to_table(dev, GENERAL_NIC) == -1)
                return -1;
 
        return 0;
 }
 
-int vnet_check()
+int vnet_unregister_device(char *dev_name)
 {
-//     struct vnet_device *(*dev)[]; -- YT
-//     struct vnet_device *dev;
-       RawEthernetPacket *pt;
-       int link_index;
-//     int i;
+    int i;
+
+    i=search_device(dev_name);
+    if (i == -1)
+        return -1;
+
+    struct vnet_if_device *device = delete_device_from_table(i);
+    if (device == NULL)
+         return -1;
+
+    V3_Free(device);
+
+    return 0;
+}
 
-       //PrintDebug("VNET: In vnet_check\n");
+int V3_Register_pkt_event(int (*netif_input)(uchar_t * pkt, uint_t size))
+{
+       return vnet_register_device("NE2000", netif_input, NULL);
 
-       V3_Yield();
+}
+int vnet_pkt_process()
+{
+       struct raw_ethernet_pkt *pt;
+       int i;
+
+       PrintDebug("VNET: In vnet_check\n");
        
-//     while (((pt = (RawEthernetPacket *)v3_dequeue(vnet_inpkt_q)) != NULL)&&((link_index = (int *)v3_dequeue(src_link_index_q)) != NULL)){
-       while ((pt = (RawEthernetPacket *)v3_dequeue(vnet_inpkt_q)) != NULL){
-#ifdef ROUTE
-/*             dev = get_device(pt);
-               //while (dev[device_num] != NULL) {     //multi-get_device -- YT
-               if (dev == NULL){
-                       PrintDebug("VNET: In vnet_check: pkt length %d, no destination device, pkt discarded\n", (int)pt->size);
-                       V3_Free(pt);
-                       continue;
-               }
-               
-               dev->input((uchar_t *)pt->data, pt->size);
+       while ((pt = (struct raw_ethernet_pkt *)v3_dequeue(g_inpkt_q)) != NULL){
 
-               PrintDebug("VNET: In vnet_check: pkt length %d, device: %s\n", (int)pt->size, dev->name);
+               PrintDebug("VNET: In vnet_check: pt length %d, pt type %d\n", (int)pt->size, (int)pt->type);
 
                for (i = 0; i <  (int)pt->size; i++)
                        PrintDebug("%x ", pt->data[i]);
                PrintDebug("\n");
-*/
-               link_index = pt->index;
-               if(HandleDataOverLink(pt, link_index)) {
-                       PrintDebug("VNET: vnet_check: Receive and Send a packet!\n");  //--YT
+       
+              if(handle_one_pkt(pt)) {
+                       PrintDebug("VNET: vnet_check: handle one packet!\n");  
                }
-#endif
-//             V3_Free(link_index);
+
                V3_Free(pt); //be careful here
        }
 
        return 0;
 }
 
-static int handler_thread(void *arg)
+static int process_tcpdata()
 {
-    struct handler *hd = (struct handler *)arg;
-
-    return vnet_handle(hd);
+       return 0;
 }
 
-static int vnet_setup_handler(int con_fd, ctype local_config, int remote_addr, int remote_port)
+static int process_udpdata()
 {
-     struct handler *h;
-
-     h = (struct handler *)V3_Malloc(sizeof(struct handler));
-        
-     if (local_config != LOCAL && local_config != REMOTE){ 
-           PrintError("VNET: bad local config\n");
-           return -1;
-     } 
-     h->local_config = local_config;
-     
-     h->local_address = bind_address;
-     h->local_port = bind_port;
 
-     h->remote_address = remote_addr;
-     h->remote_port = remote_port;
+  struct raw_ethernet_pkt *pt;
 
-     if (h->local_config == LOCAL) {
-            if ((h->fd = V3_Create_TCP_Socket() < 0)){
-                  PrintError("VNET: can't create socket\n");
-                  return -1;
-            }
-         
-            if (V3_Connect_To_IP(h->fd, h->remote_address, h->remote_port) < 0){ 
-                  V3_Close_Socket(h->fd);
-                  PrintError("VNET: can't connect to remote VNET server\n");
-                  return -1;
-            }
-
-            PrintDebug("VNET: ConnectToHost done\n");
-     } else if (local_config == REMOTE) {
-            if (con_fd < 0) {
-               PrintError("VNET: Invalid socket discriptor\n");
-               return -1;
-            }
-            h->fd = con_fd;
-     } else {
-            return -1;
-     }
+  unsigned long dest = 0;
+  unsigned short remote_port = 0;
+  SOCK link_sock = g_udp_sockfd;
+  int length = sizeof(struct raw_ethernet_pkt) - 2*sizeof(int);   //minus the "size" and "type" 
 
-     add_handler(h);
-                
-     // Now run protocol to bootstrap the remote VNET server
-     PrintDebug("VNET: socket connection done socket: %d\n", h->fd);
+  //run in a loop to get packets from outside network, adding them to the incoming packet queue
+  while (1) {
+       pt = (struct raw_ethernet_pkt *)V3_Malloc(sizeof(struct raw_ethernet_pkt));
+       if (pt == NULL){
+               PrintError("Vnet: process_udp: Malloc fails\n");
+               continue;
+       }
 
-     V3_CREATE_THREAD(&handler_thread, (void *)h, "VNET_HANDLER");
+       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);
 
-     return 0;
-}
+       if (pt->size <= 0){
+               PrintDebug("Vnet: process_udp: receiving packet from UDP fails\n");
+               V3_Free(pt);
+               return -1;
+       }
 
-static int vnet_setup_tcp()
-{
-  uint_t remote_ip;
-  uint_t remote_port;
-  int accept_socket;
-  int connection_socket;
-  uint_t server_ip =  (0 | 172 << 24 | 23 << 16 | 1 );
-  uint_t server_port = 22;
+       PrintDebug("Vnet: process_udp: get packet\n");
+       print_packet(pt->data, pt->size);
        
+       v3_enqueue(g_inpkt_q, (addr_t)pt);
 
-  if (vnet_server) {
-       if ((accept_socket = V3_Create_TCP_Socket() < 0)){
-             PrintError("VNET: Can't setup socket\n");
-             return -1;
-       }
-
-       if (bind_address == 0) {
-             if (V3_Bind_Socket(accept_socket, bind_port) < 0){ 
-                 PrintError("VNET: Can't bind socket\n");
-                 return -1;
-             }
-       } else {
-             if (0) {//BindSocketwAdx(accept_socket, bind_address, bind_port) < 0){
-                 PrintError("VNET: Can't bind socket\n");
-                 return -1;
-             }
-       }
+       //V3_Yield();
+  }
+}
 
-       if (V3_Listen_Socket(accept_socket, 1) < 0) {
-             PrintError("VNET: Can't listen socket\n");
-             return -1;
-       }
-         
-       // create new connection for each handler remotely
-       // this will stuck the initiation of vnet
-       // TODO: put this in a separate kernel thread
-       do{
-             PrintDebug("VNET: In Accepting Socket\n");
-               
-             connection_socket = V3_Accept_Socket(accept_socket, &remote_ip, &remote_port);
+static int indata_handler( )
+{
+      if (use_tcp)
+          process_tcpdata();
+      else
+          process_udpdata( );    
 
-             PrintDebug("VNET: return from Accepting Socket %d\n", connection_socket);
-            
-             if (connection_socket < 0){
-                    PrintError("VNET: Accept failed");
-                    return -1;
-             }
+      return 0;   
+}
 
-             //At this point our TCP connection is setup and running
-             vnet_setup_handler(connection_socket, REMOTE, 0, 0);
-       }while (0);
-  }else { //vnet_host
-       PrintDebug("VNET: In host status\n");
+static int start_recv_data()
+{
+       if (use_tcp){
+               
+       } else {
+               SOCK udp_data_socket;
   
-       //At this point our TCP connection is not setup
-      vnet_setup_handler(-1, LOCAL, server_ip, server_port);
-  }
+               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");
+       }
 
-  return 0;
+       V3_CREATE_THREAD(&indata_handler, NULL, "VNET_DATA_HANDLER");
+       return 0;
 }
 
-
-static int vnet_setup_udp()
+static void init_link_table()
 {
-  uint_t client_ip = (0 | 172 << 24 | 23 << 16 | 2 );
-  uint_t client_port = 22;
-  int socket;
-  uint_t server_ip =  (0 | 172 << 24 | 23 << 16 | 1 );
-  uint_t server_port = 22;
-  struct handler *hd;
-
-  hd = (struct handler *)V3_Malloc(sizeof(struct handler));
-
-  if ((socket = V3_Create_UDP_Socket()) < 0){
-             PrintError("VNET: Can't setup udp socket\n");
-             return -1; 
-  }
-
-
-  if (vnet_server) {// vnet_proxy
-       PrintDebug("VNET: In proxy status local ip: %x, %d\n", server_ip, server_port);
+    int i;
+    for (i = 0; i < MAX_LINKS; i++) {
+        g_links[i].use = 0;
+        g_links[i].next = -1;
+        g_links[i].prev = -1;
+    }
        
-       if (V3_Bind_Socket(socket, server_port) < 0){ 
-                 PrintError("VNET: Can't bind socket\n");
-                 return -1;
-       }
+    g_first_link = -1;
+    g_last_link = -1;
+    g_num_links = 0;
+}
 
-      hd->local_address = server_ip;
-      hd->local_port = server_port;
-      hd->remote_address = client_ip;
-      hd->remote_port = client_port;
-      hd->fd = socket;
-      hd->remote_config = REMOTE;      
-  }else { //vnet_host
-       PrintDebug("VNET: In host status local ip: %x\n", client_ip);
-
-       if (V3_Bind_Socket(socket, client_port) < 0){ 
-                 PrintError("VNET: Can't bind socket\n");
-                 return -1;
-       }
+static void init_device_table()
+{
+    int i;
+    for (i = 0; i < MAX_DEVICES; i++) {
+        g_devices[i].use = 0;
+        g_devices[i].next = -1;
+        g_devices[i].prev = -1;
+    }
        
-      hd->local_address = client_ip;
-      hd->local_port = client_port;
-      hd->remote_address = server_ip;
-      hd->remote_port = server_port;
-      hd->fd = socket;
-      hd->remote_config = LOCAL;
-  }
+    g_first_device = -1;
+    g_last_device = -1;
+    g_num_devices = 0;
+}
 
-  PrintDebug("VNET: vnet_setup_udp new handler: socket: %d local %x:[%d], remote %x:[%d]\n", hd->fd, hd->local_address, hd->local_port, hd->remote_address, hd->remote_port);
+static void init_route_table()
+{      
+    int i;
+    for (i = 0; i < MAX_ROUTES; i++) {
+        g_routes[i].use = 0;
+        g_routes[i].next = -1;
+        g_routes[i].prev = -1;
+    }
+       
+     g_first_route = -1;
+     g_last_route = -1;
+     g_num_routes = 0;
+}
 
-  add_handler(hd);
-                
-  PrintDebug("VNET: add handler: %d\n", hd->fd);
+static void init_tables()
+{
+    init_link_table();
+    init_device_table();
+    init_route_table();
+    init_route_cache();
+}
 
-  V3_CREATE_THREAD(&handler_thread, (void *)hd, "VNET_HANDLER");
+static void init_pkt_queue()
+{
+    PrintDebug("VNET Init package receiving queue\n");
 
-  return 0;
+    g_inpkt_q = v3_create_queue();
+    v3_init_queue(g_inpkt_q);
 }
 
-
 void vnet_init()
 {      
-       int i=0;
-
+       vnet_server = 0;
        #ifdef VNET_SERVER
-               vnet_server = 1;
+               vnet_server =1;
        #endif
 
-       extern struct v3_socket_hooks * sock_hooks;
-       PrintDebug("In VMM_SOCK: %p\n", sock_hooks);
-
-       PrintDebug("VNET Init: VNET_SERVER: %d\n", vnet_server);
-
-       vnet_inpkt_q = v3_create_queue();
-       v3_init_queue(vnet_inpkt_q);
-
-       //queue for src_link_index -- YT
-#ifdef ROUTE
-//     src_link_index_q = v3_create_queue();
-//     v3_init_queue(src_link_index_q);
-#endif
-
-       for (i = 0; i < NUM_DEVICES; i++)
-               available_devices[i] = NULL;
-
-       for (i = 0; i < NUM_HANDLERS; i++)
-               active_handlers[i] = NULL;
+       PrintDebug("VNET Init: Vnet input queue successful.\n");
 
-       if (use_tcp)
-               vnet_setup_tcp();
-       else 
-               vnet_setup_udp();
-
-      //not continue on the guest
-       //while(1){}
+       init_tables();
+       init_pkt_queue();
+       start_recv_data();
 }
 
-#if 0
-       
-static void test_send(int sock, int time)
-{
-    char *buf = "\001\002\003\004\005\006\007\008\009\010\011\012\013\014\015\n";
-    int i, j;
-    int num;
-
-    i = time;
-    while(i-- > 0){
-       num = V3_Send_pkt((uchar_t *)buf, strlen(buf));
-
-       PrintDebug("VNET: In test Send: sent size %d\n", num);
-       
-       for (j = 0; i < strlen(buf); j++)
-               PrintDebug("%x ", buf[j]);
-       PrintDebug("\n");
-    }
-}
-  
- #endif