[or-cvs] r16584: {tor} Add hidden service request history to dynamically determine (tor/branches/hidserv-perf/src/or)

chrisw at seul.org chrisw at seul.org
Mon Aug 18 16:01:08 UTC 2008


Author: chrisw
Date: 2008-08-18 12:01:08 -0400 (Mon, 18 Aug 2008)
New Revision: 16584

Modified:
   tor/branches/hidserv-perf/src/or/circuituse.c
   tor/branches/hidserv-perf/src/or/or.h
   tor/branches/hidserv-perf/src/or/rendservice.c
Log:
Add hidden service request history to dynamically determine necessary number of internal circuits.

Modified: tor/branches/hidserv-perf/src/or/circuituse.c
===================================================================
--- tor/branches/hidserv-perf/src/or/circuituse.c	2008-08-18 14:58:32 UTC (rev 16583)
+++ tor/branches/hidserv-perf/src/or/circuituse.c	2008-08-18 16:01:08 UTC (rev 16584)
@@ -431,6 +431,10 @@
   }
 
   /* Third, see if we need any more hidden service (server) circuits. */
+
+  /* Use dynamic number of internal circuits here */
+//  if (num_rend_services() && num_uptime_internal < 
+//                               get_number_of_internal_circuits_needed()) {
   if (num_rend_services() && num_uptime_internal < 3) {
     flags = (CIRCLAUNCH_NEED_CAPACITY | CIRCLAUNCH_NEED_UPTIME |
              CIRCLAUNCH_IS_INTERNAL);
@@ -702,17 +706,22 @@
             introcirc_already_open == 0) {
             
         	log_info(LD_GENERAL, "TWOINTRO First intro circ candidate %s "
-        			 "opened for service %s", circ->cpath->extend_info->nickname, TO_CIRCUIT(circ)->
+        			 "opened for service %s", 
+        			 circ->cpath->extend_info->nickname, TO_CIRCUIT(circ)->
             		 introcirc_for_edge_connection->rend_query);
                    	
         	TO_CIRCUIT(circ)->introcirc_for_edge_connection->
                               introcirc_already_open = 1;
         	rend_client_introcirc_has_opened(circ);
         } else{
-            log_info(LD_GENERAL, "TWOINTRO Second intro circ candidate %s for "
-            		 "service %s opened", circ->cpath->extend_info->nickname, TO_CIRCUIT(circ)->
-            		 introcirc_for_edge_connection->rend_query); 
-        	
+        	log_info(LD_GENERAL, "TWOINTRO Second intro circ candidate %s for "
+                     "service %s opened", 
+                     circ->cpath->extend_info->nickname, TO_CIRCUIT(circ)->
+                     introcirc_for_edge_connection->rend_query); 
+
+            /* Because this is the loser circuit, we relable it for later 
+             * usage. */
+            circ->_base.purpose = CIRCUIT_PURPOSE_C_GENERAL;
         }
         break;
     case CIRCUIT_PURPOSE_C_GENERAL:
@@ -1065,10 +1074,6 @@
     if (desired_circuit_purpose == CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT) {
       /* need to pick an intro point */
       extend_info = rend_client_get_random_intro(conn->rend_query);
-//      while (!strcmp(extend_info2->identity_digest, 
-//    		        extend_info->identity_digest)) {
-        extend_info2 = rend_client_get_random_intro(conn->rend_query);
-//      }
 
       /* TWOINTRO Select second intro point and fetch info, if neccessary */
       if (!extend_info) {
@@ -1080,7 +1085,14 @@
         conn->_base.state = AP_CONN_STATE_RENDDESC_WAIT;
         return 0;
       }
-      log_info(LD_REND,"Chose '%s' and '%s' as intro points for '%s'.",
+
+      /* TWOINTRO Select second intro point from descriptor */
+      do {
+        extend_info2 = rend_client_get_random_intro(conn->rend_query);
+      } while (extend_info2 && !strcmp(extend_info2->identity_digest, 
+		        extend_info->identity_digest));
+      
+      log_info(LD_REND,"Chose '%s' and '%s' as intro point candidates for '%s'.",
                extend_info->nickname, extend_info2->nickname, 
                safe_str(conn->rend_query));
     }

Modified: tor/branches/hidserv-perf/src/or/or.h
===================================================================
--- tor/branches/hidserv-perf/src/or/or.h	2008-08-18 14:58:32 UTC (rev 16583)
+++ tor/branches/hidserv-perf/src/or/or.h	2008-08-18 16:01:08 UTC (rev 16584)
@@ -3842,6 +3842,21 @@
 
 /********************************* rendservice.c ***************************/
 
+/** Represents a single request in the request history */
+typedef struct request_history_item {
+  long request_time; /**< Time of this request. */
+  struct request_history_item *prev; /**< Previous item in list. */
+  struct request_history_item *next; /**< Next item in list. */ 
+} request_history_item_t;
+
+/** Represents a linked list of recent service requests */
+typedef struct request_history_t {
+  long last_update; /** Time of the last history update */
+  int internal_circuits_needed; /** Number of internal circuits needed */
+  request_history_item_t *first_item; /**< First item in list. */
+  request_history_item_t *last_item; /**< Last item in list. */
+} request_history_t;
+
 int num_rend_services(void);
 int rend_config_services(or_options_t *options, int validate_only);
 int rend_service_load_keys(void);
@@ -3861,6 +3876,9 @@
                                           origin_circuit_t *circ);
 void rend_service_dump_stats(int severity);
 void rend_service_free_all(void);
+void add_service_request(request_history_t *request_history);
+int count_service_requests(request_history_t *request_history);
+int get_number_of_internal_circuits_needed(request_history_t *request_history);
 
 /********************************* rendmid.c *******************************/
 int rend_mid_establish_intro(or_circuit_t *circ, const char *request,

Modified: tor/branches/hidserv-perf/src/or/rendservice.c
===================================================================
--- tor/branches/hidserv-perf/src/or/rendservice.c	2008-08-18 14:58:32 UTC (rev 16583)
+++ tor/branches/hidserv-perf/src/or/rendservice.c	2008-08-18 16:01:08 UTC (rev 16584)
@@ -39,6 +39,16 @@
 /** How many seconds should we spend trying to connect to a requested
  * rendezvous point before giving up? */
 #define MAX_REND_TIMEOUT 30
+/** How old are service requests allowed to be until they are droped out
+ * of the request history? */
+#define SERVICE_REQUEST_HISTORY_LENGTH (60*15)
+/** How many seconds can we keep an old internal circuit value until we
+ * have to recalculate it? */
+#define REQUEST_HISTORY_UPDATE_INTERVAL (60*5) 
+/** How many internal circuits do we want to have at least? */ 
+#define MIN_INTERNAL_CIRCUITS 3
+/** How many internal circuits do we want to have at most? */
+#define MAX_INTERNAL_CIRCUITS 12
 
 /** Represents a single hidden service running at this OP. */
 typedef struct rend_service_t {
@@ -66,6 +76,8 @@
                          * up-to-date. */
   time_t next_upload_time; /**< Scheduled next hidden service descriptor
                             * upload time. */
+  request_history_t request_history; /**< History of service requests */
+  
 } rend_service_t;
 
 /** A list of rend_service_t's for services run on this OP.
@@ -858,6 +870,9 @@
            "Established circuit %d as introduction point for service %s",
            circuit->_base.n_circ_id, serviceid);
 
+  /* Add this request to the service's request history */
+  add_service_request(&service->request_history);
+  
   /* If the introduction point will not be used in an unversioned
    * descriptor, use the intro key instead of the service key in
    * ESTABLISH_INTRO. */
@@ -1462,3 +1477,103 @@
   return -1;
 }
 
+/** Add a new service request to the request history
+ */
+void
+add_service_request(request_history_t *request_history)
+{
+  /* Create a new list item for this request */
+  request_history_item_t new_request;
+  new_request.request_time = time(0);
+  
+  if (!request_history->first_item && !request_history->last_item) {
+	/* The list is not empty, so add the item to the beginning of the list */  
+    new_request.prev = NULL;
+    new_request.next = request_history->first_item;
+    request_history->first_item->prev = &new_request;
+    request_history->first_item = &new_request;
+  } else {
+    /* The list is empty, so this is the first request */
+    request_history->first_item = &new_request;
+    request_history->last_item = &new_request;
+    new_request.next = NULL;
+    new_request.prev = NULL;    
+  }
+}
+
+/** Count the number of service requests not older than 
+ * SERVICE_REQUEST_HISTORY_LENGTH seconds and delete all the ones that
+ * are older.
+ */
+int
+count_service_requests(request_history_t *request_history)
+{
+  request_history_item_t *temp;
+  request_history_item_t *to_be_deleted;
+  int number_of_requests;
+
+  long time_limit;
+
+  temp = request_history->first_item;
+  number_of_requests = 0;
+
+  /* time_limit is set to SERVICE_REQUEST_HISTORY_LENGTH seconds in the past */
+  time_limit = time(0)-(SERVICE_REQUEST_HISTORY_LENGTH*1000);
+
+  while(temp && temp->request_time > time_limit) {
+     number_of_requests++;
+     temp = temp->next;
+  }
+
+  /* temp is now pointing to the most recent request, that is older
+   * than SERVICE_REQUEST_HISTORY_LENGTH seconds. 
+   * We can delete all items from here */
+  request_history->last_item = temp;
+
+  while(temp) {
+    to_be_deleted = temp;
+    temp = temp->next;
+
+    tor_free(to_be_deleted);
+  }
+
+  request_history->last_item->next = NULL;
+  
+  
+  request_history->last_update = time(0);
+  return number_of_requests;
+}
+
+/** Return the number of internal circuits based upon the service's request
+ * history.
+ */
+int
+get_number_of_internal_circuits_needed(request_history_t *request_history)
+{
+  int requests_per_minute;
+  int internal_circuits_needed;
+
+  if (time(0) > (request_history->last_update + 
+                 REQUEST_HISTORY_UPDATE_INTERVAL)) {
+    /** The last update is more than REQUEST_HISTORY_UPDATE_INTERVAL seconds
+     * ago, so we have to recalculate it */
+
+     /** With 3 internal circuits we should be able to handle 15 requests per 
+     * minute easily. */
+    requests_per_minute = count_service_requests(request_history)/
+                          SERVICE_REQUEST_HISTORY_LENGTH;
+
+    /** For every 10 additional requests per minute we add another internal
+     * circuit. */ 
+    internal_circuits_needed = 3 + (requests_per_minute-15) * 
+                               (requests_per_minute * 10);
+
+    if (internal_circuits_needed < MIN_INTERNAL_CIRCUITS) {
+       return MIN_INTERNAL_CIRCUITS;
+    } else if (internal_circuits_needed > MAX_INTERNAL_CIRCUITS) {
+      return MAX_INTERNAL_CIRCUITS;
+    }
+    request_history->internal_circuits_needed = internal_circuits_needed;
+  }
+  return request_history->internal_circuits_needed;
+}



More information about the tor-commits mailing list