towards new core service implementation -- breaking core up into smaller modules
[oweals/gnunet.git] / src / core / gnunet-service-core_ats.c
1
2 /**
3  * How much inbound bandwidth are we supposed to be using per second?
4  */
5 static unsigned long long bandwidth_target_in_bps;
6
7 /**
8  * How much outbound bandwidth are we supposed to be using per second?
9  */
10 static unsigned long long bandwidth_target_out_bps;
11
12
13
14 /**
15  * Schedule the task that will recalculate the bandwidth
16  * quota for this peer (and possibly force a disconnect of
17  * idle peers by calculating a bandwidth of zero).
18  */
19 static void
20 schedule_quota_update (struct Neighbour *n)
21 {
22   GNUNET_assert (n->quota_update_task == GNUNET_SCHEDULER_NO_TASK);
23   n->quota_update_task =
24       GNUNET_SCHEDULER_add_delayed (QUOTA_UPDATE_FREQUENCY,
25                                     &neighbour_quota_update, n);
26 }
27
28
29 /**
30  * Function that recalculates the bandwidth quota for the
31  * given neighbour and transmits it to the transport service.
32  *
33  * @param cls neighbour for the quota update
34  * @param tc context
35  */
36 static void
37 neighbour_quota_update (void *cls,
38                         const struct GNUNET_SCHEDULER_TaskContext *tc)
39 {
40   struct Neighbour *n = cls;
41   struct GNUNET_BANDWIDTH_Value32NBO q_in;
42   struct GNUNET_BANDWIDTH_Value32NBO q_out;
43   struct GNUNET_BANDWIDTH_Value32NBO q_out_min;
44   double pref_rel;
45   double share;
46   unsigned long long distributable;
47   uint64_t need_per_peer;
48   uint64_t need_per_second;
49   unsigned int neighbour_count;
50
51 #if DEBUG_CORE > 1
52   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
53               "Neighbour quota update calculation running for peer `%4s'\n",
54               GNUNET_i2s (&n->peer));
55 #endif
56   n->quota_update_task = GNUNET_SCHEDULER_NO_TASK;
57   /* calculate relative preference among all neighbours;
58    * divides by a bit more to avoid division by zero AND to
59    * account for possibility of new neighbours joining any time
60    * AND to convert to double... */
61   neighbour_count = GNUNET_CONTAINER_multihashmap_size (neighbours);
62   if (neighbour_count == 0)
63     return;
64   if (preference_sum == 0)
65   {
66     pref_rel = 1.0 / (double) neighbour_count;
67   }
68   else
69   {
70     pref_rel = (double) n->current_preference / preference_sum;
71   }
72   need_per_peer =
73       GNUNET_BANDWIDTH_value_get_available_until (MIN_BANDWIDTH_PER_PEER,
74                                                   GNUNET_TIME_UNIT_SECONDS);
75   need_per_second = need_per_peer * neighbour_count;
76
77   /* calculate inbound bandwidth per peer */
78   distributable = 0;
79   if (bandwidth_target_in_bps > need_per_second)
80     distributable = bandwidth_target_in_bps - need_per_second;
81   share = distributable * pref_rel;
82   if (share + need_per_peer > UINT32_MAX)
83     q_in = GNUNET_BANDWIDTH_value_init (UINT32_MAX);
84   else
85     q_in = GNUNET_BANDWIDTH_value_init (need_per_peer + (uint32_t) share);
86
87   /* calculate outbound bandwidth per peer */
88   distributable = 0;
89   if (bandwidth_target_out_bps > need_per_second)
90     distributable = bandwidth_target_out_bps - need_per_second;
91   share = distributable * pref_rel;
92   if (share + need_per_peer > UINT32_MAX)
93     q_out = GNUNET_BANDWIDTH_value_init (UINT32_MAX);
94   else
95     q_out = GNUNET_BANDWIDTH_value_init (need_per_peer + (uint32_t) share);
96   n->bw_out_internal_limit = q_out;
97
98   q_out_min =
99       GNUNET_BANDWIDTH_value_min (n->bw_out_external_limit,
100                                   n->bw_out_internal_limit);
101   GNUNET_BANDWIDTH_tracker_update_quota (&n->available_send_window, n->bw_out);
102
103   /* check if we want to disconnect for good due to inactivity */
104   if ((GNUNET_TIME_absolute_get_duration (get_neighbour_timeout (n)).rel_value >
105        0) &&
106       (GNUNET_TIME_absolute_get_duration (n->time_established).rel_value >
107        GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT.rel_value))
108   {
109 #if DEBUG_CORE
110     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
111                 "Forcing disconnect of `%4s' due to inactivity\n",
112                 GNUNET_i2s (&n->peer));
113 #endif
114     GNUNET_STATISTICS_update (stats,
115                               gettext_noop ("# peers disconnected due to inactivity"), 1,
116                               GNUNET_NO);
117     q_in = GNUNET_BANDWIDTH_value_init (0);     /* force disconnect */
118   }
119 #if DEBUG_CORE_QUOTA
120   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
121               "Current quota for `%4s' is %u/%llu b/s in (old: %u b/s) / %u out (%u internal)\n",
122               GNUNET_i2s (&n->peer), (unsigned int) ntohl (q_in.value__),
123               bandwidth_target_out_bps, (unsigned int) ntohl (n->bw_in.value__),
124               (unsigned int) ntohl (n->bw_out.value__),
125               (unsigned int) ntohl (n->bw_out_internal_limit.value__));
126 #endif
127   if ((n->bw_in.value__ != q_in.value__) ||
128       (n->bw_out.value__ != q_out_min.value__))
129   {
130     if (n->bw_in.value__ != q_in.value__)
131       n->bw_in = q_in;
132     if (n->bw_out.value__ != q_out_min.value__)
133       n->bw_out = q_out_min;
134     if (GNUNET_YES == n->is_connected)
135       GNUNET_TRANSPORT_set_quota (transport, &n->peer, n->bw_in, n->bw_out);
136     handle_peer_status_change (n);
137   }
138   schedule_quota_update (n);
139 }
140
141
142
143 void
144 GSC_ATS_init ()
145 {
146   if ((GNUNET_OK !=
147        GNUNET_CONFIGURATION_get_value_number (c, "CORE", "TOTAL_QUOTA_IN",
148                                               &bandwidth_target_in_bps)) ||
149       (GNUNET_OK !=
150        GNUNET_CONFIGURATION_get_value_number (c, "CORE", "TOTAL_QUOTA_OUT",
151                                               &bandwidth_target_out_bps)) )
152   {
153     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
154                 _
155                 ("Core service is lacking key configuration settings.  Exiting.\n"));
156     GNUNET_SCHEDULER_shutdown ();
157     return;
158   }
159 }