add address test
[oweals/gnunet.git] / src / ats / gnunet-service-ats_addresses.c
index a7d18e2a5c3cd6e7758e8c121b458c707ba0c2cc..9388a66b4caca10779ab4841a0310c28daad527b 100644 (file)
@@ -36,6 +36,7 @@
 #include "gnunet-service-ats-solver_mlp.h"
 #endif
 #include "gnunet-service-ats-solver_proportional.h"
+#include "gnunet-service-ats-solver_ril.h"
 
 /**
  * NOTE: Do not change this documentation. This documentation is based on
  *    it as a value_number. If no configuration value is found it will assign
  *    GNUNET_ATS_DefaultBandwidth. The most important step is to load the
  *    configured solver using configuration "[ats]:MODE". Current solvers are
- *    MODE_SIMPLISTIC, MODE_MLP. Interaction is done using a solver API
+ *    MODE_PROPORTIONAL, MODE_MLP. Interaction is done using a solver API
  *
  *     1.4 Solver API
  *
 enum ATS_Mode
 {
   /*
-   * Simplistic mode:
+   * proportional mode:
    *
    * Assign each peer an equal amount of bandwidth (bw)
    *
    * bw_per_peer = bw_total / #active addresses
    */
-  MODE_SIMPLISTIC,
+  MODE_PROPORTIONAL,
 
   /*
    * MLP mode:
@@ -250,7 +251,14 @@ enum ATS_Mode
    * Solve ressource assignment as an optimization problem
    * Uses an mixed integer programming solver
    */
-  MODE_MLP
+  MODE_MLP,
+
+  /*
+   * Reinforcement Learning mode:
+   *
+   * Solve resource assignment using a learning agent
+   */
+  MODE_RIL
 };
 
 
@@ -367,6 +375,11 @@ struct GAS_Addresses_Handle
    */
   GAS_solver_address_change_preference s_pref;
 
+  /**
+   * Give feedback about the current assignment
+   */
+  GAS_solver_address_feedback_preference s_feedback;
+
   /**
    * Start a bulk operation
    */
@@ -399,7 +412,7 @@ struct GAS_Addresses_Handle
  */
 static unsigned int
 disassemble_ats_information (struct ATS_Address *dest,
-                                                                                                                const struct GNUNET_ATS_Information *update,
+                             const struct GNUNET_ATS_Information *update,
                              uint32_t update_count,
                              struct GNUNET_ATS_Information **delta_dest,
                              uint32_t *delta_count)
@@ -425,72 +438,71 @@ disassemble_ats_information (struct ATS_Address *dest,
 
   if (NULL == dest->atsi)
   {
-               /* Create performance information */
-               dest->atsi = GNUNET_malloc (update_count * sizeof (struct GNUNET_ATS_Information));
-               dest->atsi_count = update_count;
-               memcpy (dest->atsi, update, update_count * sizeof (struct GNUNET_ATS_Information));
-               delta_atsi_count = update_count;
-               (*delta_dest) = GNUNET_malloc (update_count * sizeof (struct GNUNET_ATS_Information));
-               for (c1 = 0; c1 < update_count; c1 ++)
-               {
-                       (*delta_dest)[c1].type = update[c1].type;
-                       (*delta_dest)[c1].value = htonl(GNUNET_ATS_VALUE_UNDEFINED);
-               }
-               (*delta_count) = update_count;
-               return GNUNET_YES;
+    /* Create performance information */
+    dest->atsi = GNUNET_malloc (update_count * sizeof (struct GNUNET_ATS_Information));
+    dest->atsi_count = update_count;
+    memcpy (dest->atsi, update, update_count * sizeof (struct GNUNET_ATS_Information));
+    (*delta_dest) = GNUNET_malloc (update_count * sizeof (struct GNUNET_ATS_Information));
+    for (c1 = 0; c1 < update_count; c1 ++)
+    {
+      (*delta_dest)[c1].type = update[c1].type;
+      (*delta_dest)[c1].value = htonl(GNUNET_ATS_VALUE_UNDEFINED);
+    }
+    (*delta_count) = update_count;
+    return GNUNET_YES;
   }
 
   for (c1 = 0; c1 < update_count; c1++)
   {
-       /* Update existing performance information */
-       found = GNUNET_NO;
-       for (c2 = 0; c2 < dest->atsi_count; c2++)
-       {
-                       if (update[c1].type == dest->atsi[c2].type)
-                       {
-                               if (update[c1].value != dest->atsi[c2].value)
-                               {
-                                               /* Save previous value in delta */
-                                               delta_atsi[delta_atsi_count] = dest->atsi[c2];
-                                               delta_atsi_count ++;
-                                               /* Set new value */
-                                               dest->atsi[c2].value = update[c1].value;
-                                               change = GNUNET_YES;
-                               }
-                               found = GNUNET_YES;
-                               break;
-                       }
-       }
-               if (GNUNET_NO == found)
-               {
-                               add_atsi[add_atsi_count] = update[c1];
-                               add_atsi_count ++;
-                               delta_atsi[delta_atsi_count].type = update[c1].type;
-                               delta_atsi[delta_atsi_count].value = htonl (GNUNET_ATS_VALUE_UNDEFINED);
-                               delta_atsi_count ++;
-               }
+    /* Update existing performance information */
+    found = GNUNET_NO;
+    for (c2 = 0; c2 < dest->atsi_count; c2++)
+    {
+      if (update[c1].type == dest->atsi[c2].type)
+      {
+        if (update[c1].value != dest->atsi[c2].value)
+        {
+          /* Save previous value in delta */
+          delta_atsi[delta_atsi_count] = dest->atsi[c2];
+          delta_atsi_count ++;
+          /* Set new value */
+          dest->atsi[c2].value = update[c1].value;
+          change = GNUNET_YES;
+        }
+        found = GNUNET_YES;
+        break;
+      }
+    }
+    if (GNUNET_NO == found)
+    {
+      add_atsi[add_atsi_count] = update[c1];
+      add_atsi_count ++;
+      delta_atsi[delta_atsi_count].type = update[c1].type;
+      delta_atsi[delta_atsi_count].value = htonl (GNUNET_ATS_VALUE_UNDEFINED);
+      delta_atsi_count ++;
+    }
   }
 
   if (add_atsi_count > 0)
   {
-               /* Extend ats performance information */
-
-               tmp_atsi = GNUNET_malloc ((dest->atsi_count + add_atsi_count) *
-                                                                                                                       (sizeof (struct GNUNET_ATS_Information)));
-               memcpy (tmp_atsi, dest->atsi, dest->atsi_count * sizeof (struct GNUNET_ATS_Information));
-               memcpy (&tmp_atsi[dest->atsi_count], add_atsi, add_atsi_count * sizeof (struct GNUNET_ATS_Information));
-               GNUNET_free (dest->atsi);
-               dest->atsi = tmp_atsi;
-               dest->atsi_count = dest->atsi_count + add_atsi_count;
-                       change = GNUNET_YES;
+    /* Extend ats performance information */
+
+    tmp_atsi = GNUNET_malloc ((dest->atsi_count + add_atsi_count) *
+                              (sizeof (struct GNUNET_ATS_Information)));
+    memcpy (tmp_atsi, dest->atsi, dest->atsi_count * sizeof (struct GNUNET_ATS_Information));
+    memcpy (&tmp_atsi[dest->atsi_count], add_atsi, add_atsi_count * sizeof (struct GNUNET_ATS_Information));
+    GNUNET_free (dest->atsi);
+    dest->atsi = tmp_atsi;
+    dest->atsi_count = dest->atsi_count + add_atsi_count;
+    change = GNUNET_YES;
   }
 
   if (delta_atsi_count > 0)
   {
-               /* Copy delta */
-               (*delta_dest) = GNUNET_malloc (delta_atsi_count * sizeof (struct GNUNET_ATS_Information));
-               memcpy ((*delta_dest), delta_atsi, delta_atsi_count * sizeof (struct GNUNET_ATS_Information));
-               (*delta_count) = delta_atsi_count;
+    /* Copy delta */
+    (*delta_dest) = GNUNET_malloc (delta_atsi_count * sizeof (struct GNUNET_ATS_Information));
+    memcpy ((*delta_dest), delta_atsi, delta_atsi_count * sizeof (struct GNUNET_ATS_Information));
+    (*delta_count) = delta_atsi_count;
   }
 
   return change;
@@ -792,8 +804,8 @@ GAS_addresses_add (struct GAS_Addresses_Handle *handle,
                       &peer->hashPubKey, new_address,
                       GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
 
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding new address %p for peer `%s' session id %u, %s\n",
-               new_address, GNUNET_i2s (peer), session_id, GNUNET_ATS_print_network_type(addr_net));
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Adding new address %p for peer `%s', length %u, session id %u, %s\n",
+               new_address, GNUNET_i2s (peer), plugin_addr_len, session_id, GNUNET_ATS_print_network_type(addr_net));
 
     /* Tell solver about new address */
     handle->s_add (handle->solver, new_address, addr_net);
@@ -841,37 +853,35 @@ GAS_addresses_add (struct GAS_Addresses_Handle *handle,
   atsi_delta_count = 0;
   if (GNUNET_YES == disassemble_ats_information (existing_address, atsi, atsi_count, &atsi_delta, &atsi_delta_count))
   {
-       /* Notify performance clients about properties */
-               GAS_performance_notify_all_clients (&existing_address->peer,
-                               existing_address->plugin,
-                               existing_address->addr, existing_address->addr_len,
-                               existing_address->session_id,
-                               existing_address->atsi, existing_address->atsi_count,
-                               existing_address->assigned_bw_out,
-                               existing_address->assigned_bw_in);
-
-               for (c1 = 0; c1 < atsi_delta_count; c1++)
-               {
-                       if ((GNUNET_ATS_NETWORK_TYPE == ntohl (atsi_delta[c1].type)) &&
-                                       (addr_net != ntohl (atsi_delta[c1].value)))
-                       {
-                               /* Network type changed */
-                               GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Address for peer `%s' %p changed from network %s to %s\n",
-                  GNUNET_i2s (peer),
-                  existing_address,
-                  GNUNET_ATS_print_network_type (addr_net),
-                  GNUNET_ATS_print_network_type (ntohl (atsi_delta[c1].value)));
-                       handle->s_address_update_network (handle->solver, existing_address,
-                                       ntohl (atsi_delta[c1].value),
-                                       get_performance_info (existing_address, GNUNET_ATS_NETWORK_TYPE));
-                       addr_net = get_performance_info (existing_address, GNUNET_ATS_NETWORK_TYPE);
-                       }
-               }
-
-               /* Notify solver about update with atsi information and session */
-         handle->s_bulk_start (handle->solver);
-         GAS_normalization_normalize_property (handle->addresses, existing_address, atsi, atsi_count);
-         handle->s_bulk_stop (handle->solver);
+    /* Notify performance clients about properties */
+    GAS_performance_notify_all_clients (&existing_address->peer,
+                existing_address->plugin,
+                existing_address->addr, existing_address->addr_len,
+                existing_address->session_id,
+                existing_address->atsi, existing_address->atsi_count,
+                existing_address->assigned_bw_out,
+                existing_address->assigned_bw_in);
+
+    for (c1 = 0; c1 < atsi_delta_count; c1++)
+    {
+      if ((GNUNET_ATS_NETWORK_TYPE == ntohl (atsi_delta[c1].type)) &&
+              (addr_net != ntohl (atsi_delta[c1].value)))
+      {
+          /* Network type changed */
+          GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Address for peer `%s' %p changed from network %s to %s\n",
+                  GNUNET_i2s (peer), existing_address,
+                  GNUNET_ATS_print_network_type (addr_net),
+                  GNUNET_ATS_print_network_type (ntohl (atsi_delta[c1].value)));
+          handle->s_address_update_network (handle->solver, existing_address,
+                  ntohl (atsi_delta[c1].value),
+                  get_performance_info (existing_address, GNUNET_ATS_NETWORK_TYPE));
+          addr_net = get_performance_info (existing_address, GNUNET_ATS_NETWORK_TYPE);
+      }
+    }
+    /* Notify solver about update with atsi information and session */
+    handle->s_bulk_start (handle->solver);
+    GAS_normalization_normalize_property (handle->addresses, existing_address, atsi, atsi_count);
+    handle->s_bulk_stop (handle->solver);
   }
   GNUNET_free_non_null (atsi_delta);
 
@@ -884,10 +894,11 @@ GAS_addresses_add (struct GAS_Addresses_Handle *handle,
   handle->s_address_update_session (handle->solver, existing_address,
                previous_session, session_id);
 
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-           "Updated existing address for peer `%s' %p with new session %u in network %s\n",
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+           "Updated existing address for peer `%s' %p length %u with new session %u in network %s\n",
            GNUNET_i2s (peer),
            existing_address,
+           existing_address->addr_len,
            session_id,
            GNUNET_ATS_print_network_type(addr_net));
 }
@@ -929,7 +940,7 @@ GAS_addresses_update (struct GAS_Addresses_Handle *handle,
 
   /* Get existing address */
   aa = find_exact_address (handle, peer, plugin_name,
-                                                                                                plugin_addr, plugin_addr_len, session_id);
+        plugin_addr, plugin_addr_len, session_id);
   if (aa == NULL)
   {
     /* GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Tried to update unknown address for peer `%s' `%s' session id %u\n", */
@@ -963,30 +974,30 @@ GAS_addresses_update (struct GAS_Addresses_Handle *handle,
   atsi_delta_count = 0;
   if (GNUNET_YES == disassemble_ats_information (aa, atsi, atsi_count, &atsi_delta, &atsi_delta_count))
   {
-       /* ATS properties changed */
-       for (c1 = 0; c1 < atsi_delta_count; c1++)
-       {
-               if (GNUNET_ATS_NETWORK_TYPE == ntohl (atsi_delta[c1].type))
-               {
-                       /* Network type changed */
-                       handle->s_address_update_network (handle->solver, aa,
-                                       ntohl (atsi_delta[c1].value),
-                                       get_performance_info (aa, GNUNET_ATS_NETWORK_TYPE));
-               }
-       }
-
-               /* Notify performance clients about updated address */
-               GAS_performance_notify_all_clients (&aa->peer,
-                               aa->plugin,
-                               aa->addr, aa->addr_len,
-                               aa->session_id,
-                               aa->atsi, aa->atsi_count,
-                               aa->assigned_bw_out,
-                               aa->assigned_bw_in);
-
-               handle->s_bulk_start (handle->solver);
-               GAS_normalization_normalize_property (handle->addresses, aa, atsi, atsi_count);
-               handle->s_bulk_stop (handle->solver);
+    /* ATS properties changed */
+    for (c1 = 0; c1 < atsi_delta_count; c1++)
+    {
+        if (GNUNET_ATS_NETWORK_TYPE == ntohl (atsi_delta[c1].type))
+        {
+            /* Network type changed */
+            handle->s_address_update_network (handle->solver, aa,
+                      ntohl (atsi_delta[c1].value),
+                      get_performance_info (aa, GNUNET_ATS_NETWORK_TYPE));
+        }
+    }
+
+    /* Notify performance clients about updated address */
+    GAS_performance_notify_all_clients (&aa->peer,
+                    aa->plugin,
+                    aa->addr, aa->addr_len,
+                    aa->session_id,
+                    aa->atsi, aa->atsi_count,
+                    aa->assigned_bw_out,
+                    aa->assigned_bw_in);
+
+    handle->s_bulk_start (handle->solver);
+    GAS_normalization_normalize_property (handle->addresses, aa, atsi, atsi_count);
+    handle->s_bulk_stop (handle->solver);
   }
   GNUNET_free_non_null (atsi_delta);
 }
@@ -1038,7 +1049,7 @@ destroy_by_session_id (void *cls, const struct GNUNET_HashCode * key, void *valu
         (0 == memcmp (des->addr, aa->addr, aa->addr_len)))
     {
 
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+      GNUNET_log (GNUNET_ERROR_TYPE_INFO,
                   "Deleting full address for peer `%s' session %u %p\n",
                   GNUNET_i2s (&aa->peer), aa->session_id, aa);
 
@@ -1071,7 +1082,7 @@ destroy_by_session_id (void *cls, const struct GNUNET_HashCode * key, void *valu
     if (aa->addr_len == 0)
     {
         /* Inbound connection died, delete full address */
-        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+        GNUNET_log (GNUNET_ERROR_TYPE_INFO,
                     "Deleting inbound address for peer `%s': `%s' session %u\n",
                     GNUNET_i2s (&aa->peer), aa->plugin, aa->session_id);
 
@@ -1087,12 +1098,13 @@ destroy_by_session_id (void *cls, const struct GNUNET_HashCode * key, void *valu
     else
     {
         /* Session died */
-        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+        GNUNET_log (GNUNET_ERROR_TYPE_INFO,
                     "Deleting session for peer `%s': `%s' %u\n",
                     GNUNET_i2s (&aa->peer), aa->plugin, aa->session_id);
         /* Notify solver to delete session */
         handle->s_del (handle->solver, aa, GNUNET_YES);
         aa->session_id = 0;
+        aa->active = GNUNET_NO;
         return GNUNET_OK;
     }
   }
@@ -1190,7 +1202,7 @@ GAS_addresses_in_use (struct GAS_Addresses_Handle *handle,
   if (NULL == ea)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Trying to set unknown address `%s', %s %u %s \n",
+                "Trying to set unknown address `%s' `%s' `%u' to %s \n",
                 GNUNET_i2s (peer),
                 plugin_name, session_id,
                 (GNUNET_NO == in_use) ? "NO" : "YES");
@@ -1251,6 +1263,23 @@ GAS_addresses_request_address_cancel (struct GAS_Addresses_Handle *handle,
   GNUNET_free (cur);
 }
 
+/*
+static int
+addrinfo_it (void *cls, const struct GNUNET_HashCode *key, void *value)
+{
+       static int count = 0;
+       struct GNUNET_PeerIdentity *id = cls;
+       struct ATS_Address *aa = value;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "[%u] Peer `%s' %s length %u session %u active %s\n",
+              count, GNUNET_i2s (id), aa->plugin, aa->addr_len, aa->session_id,
+              (GNUNET_YES == aa->active) ? "active" : "inactive");
+
+  count ++;
+       return GNUNET_OK;
+}
+*/
 
 /**
  * Request address suggestions for a peer
@@ -1265,7 +1294,7 @@ GAS_addresses_request_address (struct GAS_Addresses_Handle *handle,
   struct GAS_Addresses_Suggestion_Requests *cur = handle->r_head;
   struct ATS_Address *aa;
 
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
               "Received `%s' for peer `%s'\n",
               "REQUEST ADDRESS",
               GNUNET_i2s (peer));
@@ -1285,11 +1314,18 @@ GAS_addresses_request_address (struct GAS_Addresses_Handle *handle,
       GNUNET_CONTAINER_DLL_insert (handle->r_head, handle->r_tail, cur);
   }
 
+  /*
+   * Debuging information about addresses
+   *
+   * GNUNET_CONTAINER_multihashmap_get_multiple(handle->addresses,
+   *  &peer->hashPubKey, &addrinfo_it, (void *) peer);
+   */
+
   /* Get prefered address from solver */
   aa = (struct ATS_Address *) handle->s_get (handle->solver, peer);
   if (NULL == aa)
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
                 "Cannot suggest address for peer `%s'\n", GNUNET_i2s (peer));
     return;
   }
@@ -1372,12 +1408,13 @@ GAS_addresses_handle_backoff_reset (struct GAS_Addresses_Handle *handle,
  */
 static void
 normalized_preference_changed_cb (void *cls,
-                                                                 const struct GNUNET_PeerIdentity *peer,
-                                                                 enum GNUNET_ATS_PreferenceKind kind,
-                                                                 double pref_rel)
+                                  const struct GNUNET_PeerIdentity *peer,
+                                  enum GNUNET_ATS_PreferenceKind kind,
+                                  double pref_rel)
 {
-       GNUNET_assert (NULL != cls);
-       struct GAS_Addresses_Handle *handle = cls;
+  GNUNET_assert (NULL != cls);
+  struct GAS_Addresses_Handle *handle = cls;
+
   /* Tell solver about update */
   handle->s_pref (handle->solver, peer, kind, pref_rel);
 }
@@ -1393,24 +1430,20 @@ normalized_preference_changed_cb (void *cls,
  */
 static void
 normalized_property_changed_cb (void *cls,
-                                                                                                                 struct ATS_Address *address,
-                                                                                                                 uint32_t type,
-                                                                                                                 double prop_rel)
+                                struct ATS_Address *address,
+                                uint32_t type,
+                                double prop_rel)
 {
-       struct GAS_Addresses_Handle *ah = (struct GAS_Addresses_Handle *) cls;
-       GNUNET_assert (NULL != ah);
-
-       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Normalized property %s for peer `%s' changed to %.3f \n",
-              GNUNET_ATS_print_property_type (type),
-              GNUNET_i2s (&address->peer),
-              prop_rel);
-
-       ah->s_address_update_property (ah->solver,
-                                                                                                                               address,
-                                                                                                                               type,
-                                                                                                                               0,
-                                                                                                                               prop_rel);
+  struct GAS_Addresses_Handle *ah = (struct GAS_Addresses_Handle *) cls;
+  GNUNET_assert (NULL != ah);
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+        "Normalized property %s for peer `%s' changed to %.3f \n",
+        GNUNET_ATS_print_property_type (type),
+        GNUNET_i2s (&address->peer),
+        prop_rel);
+
+  ah->s_address_update_property (ah->solver, address, type, 0, prop_rel);
 }
 
 
@@ -1458,10 +1491,10 @@ GAS_addresses_change_preference (struct GAS_Addresses_Handle *handle,
                                  enum GNUNET_ATS_PreferenceKind kind,
                                  float score_abs)
 {
-       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Received `%s' for peer `%s' for client %p\n",
-              "CHANGE PREFERENCE",
-              GNUNET_i2s (peer), client);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+        "Received `%s' for peer `%s' for client %p\n",
+        "CHANGE PREFERENCE",
+        GNUNET_i2s (peer), client);
 
   if (GNUNET_NO == handle->running)
     return;
@@ -1483,6 +1516,46 @@ GAS_addresses_change_preference (struct GAS_Addresses_Handle *handle,
 }
 
 
+/**
+ * Change the preference for a peer
+ *
+ * @param handle the address handle
+ * @param application the client sending this request
+ * @param peer the peer id
+ * @param scope the time interval for this feedback: [now - scope .. now]
+ * @param kind the preference kind to change
+ * @param score_abs the new preference score
+ */
+void
+GAS_addresses_preference_feedback (struct GAS_Addresses_Handle *handle,
+                                  void *application,
+                                  const struct GNUNET_PeerIdentity *peer,
+                                  const struct GNUNET_TIME_Relative scope,
+                                  enum GNUNET_ATS_PreferenceKind kind,
+                                  float score_abs)
+{
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+        "Received `%s' for peer `%s' for client %p\n",
+        "PREFERENCE FEEDBACK",
+        GNUNET_i2s (peer), application);
+
+  if (GNUNET_NO == handle->running)
+    return;
+
+  if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (handle->addresses,
+                                                          &peer->hashPubKey))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "Received `%s' for unknown peer `%s' from client %p\n",
+                "PREFERENCE FEEDBACK",
+                GNUNET_i2s (peer), application);
+    return;
+  }
+
+  handle->s_feedback (handle->solver, application, peer, scope, kind, score_abs);
+}
+
+
 /**
  * Load quotas for networks from configuration
  *
@@ -1493,7 +1566,10 @@ GAS_addresses_change_preference (struct GAS_Addresses_Handle *handle,
  * @return number of networks loaded
  */
 static unsigned int
-load_quotas (const struct GNUNET_CONFIGURATION_Handle *cfg, unsigned long long *out_dest, unsigned long long *in_dest, int dest_length)
+load_quotas (const struct GNUNET_CONFIGURATION_Handle *cfg,
+            unsigned long long *out_dest,
+            unsigned long long *in_dest,
+            int dest_length)
 {
   char *network_str[GNUNET_ATS_NetworkTypeCount] = GNUNET_ATS_NetworkTypeString;
   char * entry_in = NULL;
@@ -1600,7 +1676,8 @@ bandwidth_changed_cb (void *cls, struct ATS_Address *address)
   GNUNET_assert (handle != NULL);
   GNUNET_assert (address != NULL);
 
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Bandwidth assignment changed for peer %s \n", GNUNET_i2s(&address->peer));
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Bandwidth assignment changed for peer %s \n",
+               GNUNET_i2s(&address->peer));
 
   /* Notify performance clients about changes to address */
   GAS_performance_notify_all_clients (&address->peer,
@@ -1619,13 +1696,26 @@ bandwidth_changed_cb (void *cls, struct ATS_Address *address)
   }
   if (NULL == cur)
   {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+      GNUNET_log (GNUNET_ERROR_TYPE_INFO,
                   "Nobody is interested in peer `%s' :(\n",GNUNET_i2s (&address->peer));
       return;
   }
 
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Sending bandwidth update for peer `%s'\n",GNUNET_i2s (&address->peer));
+  if ((0 == ntohl (address->assigned_bw_in.value__)) &&
+               (0 == ntohl (address->assigned_bw_out.value__)))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "Telling transport to disconnect peer `%s'\n",
+                GNUNET_i2s (&address->peer));
+  }
+  else
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "Sending bandwidth update for peer `%s': %llu %llu\n",
+                GNUNET_i2s (&address->peer),
+                address->assigned_bw_out,
+                address->assigned_bw_out);
+  }
 
   /* *Notify scheduling clients about suggestion */
   GAS_scheduling_transmit_address_suggestion (&address->peer,
@@ -1642,7 +1732,7 @@ bandwidth_changed_cb (void *cls, struct ATS_Address *address)
  * Initialize address subsystem. The addresses subsystem manages the addresses
  * known and current performance information. It has a solver component
  * responsible for the resource allocation. It tells the solver about changes
- * and receives updates when the solver changes the ressource allocation.
+ * and receives updates when the solver changes the resource allocation.
  *
  * @param cfg configuration to use
  * @param stats the statistics handle to use
@@ -1671,29 +1761,33 @@ GAS_addresses_init (const struct GNUNET_CONFIGURATION_Handle *cfg,
   /* Figure out configured solution method */
   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg, "ats", "MODE", &mode_str))
   {
-      GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "No ressource assignment method configured, using simplistic approch\n");
-      ah->ats_mode = MODE_SIMPLISTIC;
+      GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "No resource assignment method configured, using proportional approach\n");
+      ah->ats_mode = MODE_PROPORTIONAL;
   }
   else
   {
       for (c = 0; c < strlen (mode_str); c++)
         mode_str[c] = toupper (mode_str[c]);
-      if (0 == strcmp (mode_str, "SIMPLISTIC"))
+      if (0 == strcmp (mode_str, "PROPORTIONAL"))
       {
-          ah->ats_mode = MODE_SIMPLISTIC;
+          ah->ats_mode = MODE_PROPORTIONAL;
       }
       else if (0 == strcmp (mode_str, "MLP"))
       {
           ah->ats_mode = MODE_MLP;
 #if !HAVE_LIBGLPK
-          GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Assignment method `%s' configured, but GLPK is not availabe, please install \n", mode_str);
-          ah->ats_mode = MODE_SIMPLISTIC;
+          GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Assignment method `%s' configured, but GLPK is not available, please install \n", mode_str);
+          ah->ats_mode = MODE_PROPORTIONAL;
 #endif
       }
+      else if (0 == strcmp (mode_str, "RIL"))
+      {
+         ah->ats_mode = MODE_RIL;
+      }
       else
       {
-          GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Invalid ressource assignment method `%s' configured, using simplistic approch\n", mode_str);
-          ah->ats_mode = MODE_SIMPLISTIC;
+          GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Invalid resource assignment method `%s' configured, using proportional approach\n", mode_str);
+          ah->ats_mode = MODE_PROPORTIONAL;
       }
       GNUNET_free (mode_str);
   }
@@ -1703,7 +1797,6 @@ GAS_addresses_init (const struct GNUNET_CONFIGURATION_Handle *cfg,
     case MODE_MLP:
       /* Init the MLP solver with default values */
 #if HAVE_LIBGLPK
-      ah->ats_mode = MODE_MLP;
       ah->s_init = &GAS_mlp_init;
       ah->s_add = &GAS_mlp_address_add;
       ah->s_address_update_property = &GAS_mlp_address_property_changed;
@@ -1713,6 +1806,7 @@ GAS_addresses_init (const struct GNUNET_CONFIGURATION_Handle *cfg,
       ah->s_get = &GAS_mlp_get_preferred_address;
       ah->s_get_stop = &GAS_mlp_stop_get_preferred_address;
       ah->s_pref = &GAS_mlp_address_change_preference;
+      ah->s_feedback = &GAS_mlp_address_preference_feedback;
       ah->s_del =  &GAS_mlp_address_delete;
       ah->s_bulk_start = &GAS_mlp_bulk_start;
       ah->s_bulk_stop = &GAS_mlp_bulk_stop;
@@ -1722,9 +1816,8 @@ GAS_addresses_init (const struct GNUNET_CONFIGURATION_Handle *cfg,
       return NULL;
 #endif
       break;
-    case MODE_SIMPLISTIC:
-      /* Init the simplistic solver with default values */
-      ah->ats_mode = MODE_SIMPLISTIC;
+    case MODE_PROPORTIONAL:
+      /* Init the proportional solver with default values */
       ah->s_init = &GAS_proportional_init;
       ah->s_add = &GAS_proportional_address_add;
       ah->s_address_update_property = &GAS_proportional_address_property_changed;
@@ -1734,12 +1827,31 @@ GAS_addresses_init (const struct GNUNET_CONFIGURATION_Handle *cfg,
       ah->s_get = &GAS_proportional_get_preferred_address;
       ah->s_get_stop = &GAS_proportional_stop_get_preferred_address;
       ah->s_pref = &GAS_proportional_address_change_preference;
+      ah->s_feedback = &GAS_proportional_address_preference_feedback;
       ah->s_del  = &GAS_proportional_address_delete;
       ah->s_bulk_start = &GAS_proportional_bulk_start;
       ah->s_bulk_stop = &GAS_proportional_bulk_stop;
       ah->s_done = &GAS_proportional_done;
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ATS started in %s mode\n", "SIMPLISTIC");
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ATS started in %s mode\n", "PROPORTIONAL");
       break;
+    case MODE_RIL:
+      /* Init the ril solver with default values */
+         ah->s_init = &GAS_ril_init;
+         ah->s_add = &GAS_ril_address_add;
+         ah->s_address_update_property = &GAS_ril_address_property_changed;
+         ah->s_address_update_session = &GAS_ril_address_session_changed;
+         ah->s_address_update_inuse = &GAS_ril_address_inuse_changed;
+         ah->s_address_update_network = &GAS_ril_address_change_network;
+         ah->s_get = &GAS_ril_get_preferred_address;
+         ah->s_get_stop = &GAS_ril_stop_get_preferred_address;
+         ah->s_pref = &GAS_ril_address_change_preference;
+         ah->s_feedback = &GAS_ril_address_preference_feedback;
+         ah->s_del  = &GAS_ril_address_delete;
+         ah->s_bulk_start = &GAS_ril_bulk_start;
+         ah->s_bulk_stop = &GAS_ril_bulk_stop;
+         ah->s_done = &GAS_ril_done;
+         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ATS started in %s mode\n", "RIL");
+         break;
     default:
       return NULL;
       break;
@@ -1754,6 +1866,7 @@ GAS_addresses_init (const struct GNUNET_CONFIGURATION_Handle *cfg,
   GNUNET_assert (NULL != ah->s_get);
   GNUNET_assert (NULL != ah->s_get_stop);
   GNUNET_assert (NULL != ah->s_pref);
+  GNUNET_assert (NULL != ah->s_feedback);
   GNUNET_assert (NULL != ah->s_del);
   GNUNET_assert (NULL != ah->s_done);
   GNUNET_assert (NULL != ah->s_bulk_start);
@@ -1817,11 +1930,12 @@ GAS_addresses_destroy_all (struct GAS_Addresses_Handle *handle)
   if (GNUNET_NO == handle->running)
     return;
 
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Received `%s'\n",
-              "DESTROY ALL");
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Destroying all addresses\n");
+  handle->s_bulk_start (handle->solver);
   if (handle->addresses != NULL)
     GNUNET_CONTAINER_multihashmap_iterate (handle->addresses, &destroy_all_address_it, handle);
+  handle->s_bulk_start (handle->solver);
 }
 
 
@@ -1835,7 +1949,7 @@ GAS_addresses_done (struct GAS_Addresses_Handle *handle)
 {
   struct GAS_Addresses_Suggestion_Requests *cur;
 
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
               "Shutting down addresses\n");
   GNUNET_assert (NULL != handle);
   GAS_addresses_destroy_all (handle);