aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2010-03-05 20:31:58 +0000
committerChristian Grothoff <christian@grothoff.org>2010-03-05 20:31:58 +0000
commitcb4610c2c23191e0977738402d87e7b6bd0808c9 (patch)
treebb6f7ad28dd92895680c909adbe3d54a3cce62b6
parent78a3d311f2c3c82affe6003b9bd3c17c0b2d200b (diff)
downloadgnunet-cb4610c2c23191e0977738402d87e7b6bd0808c9.tar.gz
gnunet-cb4610c2c23191e0977738402d87e7b6bd0808c9.zip
trying to fix bandwidth calculations
-rw-r--r--src/core/core.h10
-rw-r--r--src/core/core_api_peer_get_info.c21
-rw-r--r--src/core/gnunet-service-core.c360
-rw-r--r--src/fs/gnunet-service-fs.c6
-rw-r--r--src/include/Makefile.am1
-rw-r--r--src/include/gnunet_constants.h12
-rw-r--r--src/include/gnunet_core_service.h12
-rw-r--r--src/include/gnunet_transport_service.h9
-rw-r--r--src/include/gnunet_util_lib.h1
-rw-r--r--src/topology/gnunet-daemon-topology.c31
-rw-r--r--src/topology/test_gnunet_service_topology_data.conf1
-rw-r--r--src/transport/gnunet-service-transport.c214
-rw-r--r--src/transport/plugin_transport_tcp.c2
-rw-r--r--src/transport/test_transport_api.c2
-rw-r--r--src/transport/transport.h21
-rw-r--r--src/transport/transport_api.c155
16 files changed, 356 insertions, 502 deletions
diff --git a/src/core/core.h b/src/core/core.h
index d74ee06f6..45d138140 100644
--- a/src/core/core.h
+++ b/src/core/core.h
@@ -211,7 +211,7 @@ struct RequestInfoMessage
211 * peer to at most the specified amount (naturally, the 211 * peer to at most the specified amount (naturally, the
212 * amount is also limited by the receiving peer). 212 * amount is also limited by the receiving peer).
213 */ 213 */
214 uint32_t limit_outbound_bpm GNUNET_PACKED; 214 struct GNUNET_BANDWIDTH_Value32NBO limit_outbound;
215 215
216 /** 216 /**
217 * Number of bytes of inbound traffic to reserve, can 217 * Number of bytes of inbound traffic to reserve, can
@@ -253,16 +253,16 @@ struct ConfigurationInfoMessage
253 int32_t reserved_amount GNUNET_PACKED; 253 int32_t reserved_amount GNUNET_PACKED;
254 254
255 /** 255 /**
256 * Available bandwidth in (in bytes per minute) for this peer. 256 * Available bandwidth in for this peer.
257 * 0 if we have been disconnected. 257 * 0 if we have been disconnected.
258 */ 258 */
259 uint32_t bpm_in GNUNET_PACKED; 259 struct GNUNET_BANDWIDTH_Value32NBO bw_in;
260 260
261 /** 261 /**
262 * Available bandwidth out (in bytes per minute) for this peer, 262 * Available bandwidth out for this peer,
263 * 0 if we have been disconnected. 263 * 0 if we have been disconnected.
264 */ 264 */
265 uint32_t bpm_out GNUNET_PACKED; 265 struct GNUNET_BANDWIDTH_Value32NBO bw_out;
266 266
267 /** 267 /**
268 * Current traffic preference for the peer. 268 * Current traffic preference for the peer.
diff --git a/src/core/core_api_peer_get_info.c b/src/core/core_api_peer_get_info.c
index cd963375f..c28ae2feb 100644
--- a/src/core/core_api_peer_get_info.c
+++ b/src/core/core_api_peer_get_info.c
@@ -61,12 +61,13 @@ receive_info (void *cls,
61{ 61{
62 struct GNUNET_CORE_InformationRequestContext *irc = cls; 62 struct GNUNET_CORE_InformationRequestContext *irc = cls;
63 const struct ConfigurationInfoMessage *cim; 63 const struct ConfigurationInfoMessage *cim;
64 static struct GNUNET_BANDWIDTH_Value32NBO zbw; /* zero bandwidth */
64 65
65 if (msg == NULL) 66 if (msg == NULL)
66 { 67 {
67 if (irc->info != NULL) 68 if (irc->info != NULL)
68 irc->info (irc->info_cls, 69 irc->info (irc->info_cls,
69 NULL, 0, 0, 0, 0); 70 NULL, zbw, zbw, 0, 0);
70 GNUNET_CLIENT_disconnect (irc->client); 71 GNUNET_CLIENT_disconnect (irc->client);
71 GNUNET_free (irc); 72 GNUNET_free (irc);
72 return; 73 return;
@@ -77,7 +78,7 @@ receive_info (void *cls,
77 GNUNET_break (0); 78 GNUNET_break (0);
78 if (irc->info != NULL) 79 if (irc->info != NULL)
79 irc->info (irc->info_cls, 80 irc->info (irc->info_cls,
80 NULL, 0, 0, 0, 0); 81 NULL, zbw, zbw, 0, 0);
81 GNUNET_CLIENT_disconnect (irc->client); 82 GNUNET_CLIENT_disconnect (irc->client);
82 GNUNET_free (irc); 83 GNUNET_free (irc);
83 return; 84 return;
@@ -86,8 +87,8 @@ receive_info (void *cls,
86 if (irc->info != NULL) 87 if (irc->info != NULL)
87 irc->info (irc->info_cls, 88 irc->info (irc->info_cls,
88 &cim->peer, 89 &cim->peer,
89 ntohl (cim->bpm_in), 90 cim->bw_in,
90 ntohl (cim->bpm_out), 91 cim->bw_out,
91 ntohl (cim->reserved_amount), 92 ntohl (cim->reserved_amount),
92 GNUNET_ntohll (cim->preference)); 93 GNUNET_ntohll (cim->preference));
93 GNUNET_CLIENT_disconnect (irc->client); 94 GNUNET_CLIENT_disconnect (irc->client);
@@ -103,11 +104,11 @@ receive_info (void *cls,
103 * @param peer identifies the peer 104 * @param peer identifies the peer
104 * @param timeout after how long should we give up (and call "info" with NULL 105 * @param timeout after how long should we give up (and call "info" with NULL
105 * for "peer" to signal an error)? 106 * for "peer" to signal an error)?
106 * @param bpm_out set to the current bandwidth limit (sending) for this peer, 107 * @param bw_out set to the current bandwidth limit (sending) for this peer,
107 * caller should set "bpm_out" to "-1" to avoid changing 108 * caller should set "bw_out" to "-1" to avoid changing
108 * the current value; otherwise "bpm_out" will be lowered to 109 * the current value; otherwise "bw_out" will be lowered to
109 * the specified value; passing a pointer to "0" can be used to force 110 * the specified value; passing a pointer to "0" can be used to force
110 * us to disconnect from the peer; "bpm_out" might not increase 111 * us to disconnect from the peer; "bw_out" might not increase
111 * as specified since the upper bound is generally 112 * as specified since the upper bound is generally
112 * determined by the other peer! 113 * determined by the other peer!
113 * @param amount reserve N bytes for receiving, negative 114 * @param amount reserve N bytes for receiving, negative
@@ -125,7 +126,7 @@ GNUNET_CORE_peer_change_preference (struct GNUNET_SCHEDULER_Handle *sched,
125 const struct GNUNET_CONFIGURATION_Handle *cfg, 126 const struct GNUNET_CONFIGURATION_Handle *cfg,
126 const struct GNUNET_PeerIdentity *peer, 127 const struct GNUNET_PeerIdentity *peer,
127 struct GNUNET_TIME_Relative timeout, 128 struct GNUNET_TIME_Relative timeout,
128 uint32_t bpm_out, 129 struct GNUNET_BANDWIDTH_Value32NBO bw_out,
129 int32_t amount, 130 int32_t amount,
130 uint64_t preference, 131 uint64_t preference,
131 GNUNET_CORE_PeerConfigurationInfoCallback info, 132 GNUNET_CORE_PeerConfigurationInfoCallback info,
@@ -146,7 +147,7 @@ GNUNET_CORE_peer_change_preference (struct GNUNET_SCHEDULER_Handle *sched,
146 rim.header.size = htons (sizeof (struct RequestInfoMessage)); 147 rim.header.size = htons (sizeof (struct RequestInfoMessage));
147 rim.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_REQUEST_INFO); 148 rim.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_REQUEST_INFO);
148 rim.reserved = htonl (0); 149 rim.reserved = htonl (0);
149 rim.limit_outbound_bpm = htonl (bpm_out); 150 rim.limit_outbound = bw_out;
150 rim.reserve_inbound = htonl (amount); 151 rim.reserve_inbound = htonl (amount);
151 rim.preference_change = GNUNET_htonll(preference); 152 rim.preference_change = GNUNET_htonll(preference);
152 rim.peer = *peer; 153 rim.peer = *peer;
diff --git a/src/core/gnunet-service-core.c b/src/core/gnunet-service-core.c
index 0001fccbf..85be80101 100644
--- a/src/core/gnunet-service-core.c
+++ b/src/core/gnunet-service-core.c
@@ -48,9 +48,9 @@
48/** 48/**
49 * Receive and send buffer windows grow over time. For 49 * Receive and send buffer windows grow over time. For
50 * how long can 'unused' bandwidth accumulate before we 50 * how long can 'unused' bandwidth accumulate before we
51 * need to cap it? (specified in ms). 51 * need to cap it? (specified in seconds).
52 */ 52 */
53#define MAX_WINDOW_TIME (5 * 60 * 1000) 53#define MAX_WINDOW_TIME_S (5 * 60)
54 54
55/** 55/**
56 * How many messages do we queue up at most for optional 56 * How many messages do we queue up at most for optional
@@ -60,17 +60,11 @@
60#define MAX_NOTIFY_QUEUE 16 60#define MAX_NOTIFY_QUEUE 16
61 61
62/** 62/**
63 * Minimum of bytes per minute (out) to assign to any connected peer. 63 * Minimum bandwidth (out) to assign to any connected peer.
64 * Should be rather low; values larger than DEFAULT_BPM_IN_OUT make no 64 * Should be rather low; values larger than DEFAULT_BW_IN_OUT make no
65 * sense. 65 * sense.
66 */ 66 */
67#define MIN_BPM_PER_PEER GNUNET_CONSTANTS_DEFAULT_BPM_IN_OUT 67#define MIN_BANDWIDTH_PER_PEER GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT
68
69/**
70 * What is the smallest change (in number of bytes per minute)
71 * that we consider significant enough to bother triggering?
72 */
73#define MIN_BPM_CHANGE 32
74 68
75/** 69/**
76 * After how much time past the "official" expiration time do 70 * After how much time past the "official" expiration time do
@@ -84,27 +78,27 @@
84/** 78/**
85 * What is the maximum delay for a SET_KEY message? 79 * What is the maximum delay for a SET_KEY message?
86 */ 80 */
87#define MAX_SET_KEY_DELAY GNUNET_TIME_UNIT_SECONDS 81#define MAX_SET_KEY_DELAY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
88 82
89/** 83/**
90 * What how long do we wait for SET_KEY confirmation initially? 84 * What how long do we wait for SET_KEY confirmation initially?
91 */ 85 */
92#define INITIAL_SET_KEY_RETRY_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 3) 86#define INITIAL_SET_KEY_RETRY_FREQUENCY GNUNET_TIME_relative_multiply (MAX_SET_KEY_DELAY, 3)
93 87
94/** 88/**
95 * What is the maximum delay for a PING message? 89 * What is the maximum delay for a PING message?
96 */ 90 */
97#define MAX_PING_DELAY GNUNET_TIME_UNIT_SECONDS 91#define MAX_PING_DELAY GNUNET_TIME_relative_multiply (MAX_SET_KEY_DELAY, 2)
98 92
99/** 93/**
100 * What is the maximum delay for a PONG message? 94 * What is the maximum delay for a PONG message?
101 */ 95 */
102#define MAX_PONG_DELAY GNUNET_TIME_UNIT_SECONDS 96#define MAX_PONG_DELAY GNUNET_TIME_relative_multiply (MAX_PING_DELAY, 2)
103 97
104/** 98/**
105 * How often do we recalculate bandwidth quotas? 99 * How often do we recalculate bandwidth quotas?
106 */ 100 */
107#define QUOTA_UPDATE_FREQUENCY GNUNET_TIME_UNIT_SECONDS 101#define QUOTA_UPDATE_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
108 102
109/** 103/**
110 * What is the priority for a SET_KEY message? 104 * What is the priority for a SET_KEY message?
@@ -206,11 +200,10 @@ struct EncryptedMessage
206 uint32_t sequence_number GNUNET_PACKED; 200 uint32_t sequence_number GNUNET_PACKED;
207 201
208 /** 202 /**
209 * Desired bandwidth (how much we should send to this 203 * Desired bandwidth (how much we should send to this peer / how
210 * peer / how much is the sender willing to receive), 204 * much is the sender willing to receive)?
211 * in bytes per minute.
212 */ 205 */
213 uint32_t inbound_bpm_limit GNUNET_PACKED; 206 struct GNUNET_BANDWIDTH_Value32NBO inbound_bw_limit;
214 207
215 /** 208 /**
216 * Timestamp. Used to prevent reply of ancient messages 209 * Timestamp. Used to prevent reply of ancient messages
@@ -271,10 +264,9 @@ struct PongMessage
271 264
272 /** 265 /**
273 * Desired bandwidth (how much we should send to this 266 * Desired bandwidth (how much we should send to this
274 * peer / how much is the sender willing to receive), 267 * peer / how much is the sender willing to receive).
275 * in bytes per minute.
276 */ 268 */
277 uint32_t inbound_bpm_limit GNUNET_PACKED; 269 struct GNUNET_BANDWIDTH_Value32NBO inbound_bw_limit;
278 270
279 /** 271 /**
280 * Intended target of the PING, used primarily to check 272 * Intended target of the PING, used primarily to check
@@ -510,32 +502,14 @@ struct Neighbour
510 struct GNUNET_TIME_Relative set_key_retry_frequency; 502 struct GNUNET_TIME_Relative set_key_retry_frequency;
511 503
512 /** 504 /**
513 * Time of our last update to the "available_send_window". 505 * Tracking bandwidth for sending to this peer.
514 */
515 struct GNUNET_TIME_Absolute last_asw_update;
516
517 /**
518 * Time of our last update to the "available_recv_window".
519 */
520 struct GNUNET_TIME_Absolute last_arw_update;
521
522 /**
523 * Number of bytes that we are eligible to transmit to this
524 * peer at this point. Incremented every minute by max_out_bpm,
525 * bounded by max_bpm (no back-log larger than MAX_BUF_FACT minutes,
526 * bandwidth-hogs are sampled at a frequency of about 78s!);
527 * may get negative if we have VERY high priority content.
528 */ 506 */
529 long long available_send_window; 507 struct GNUNET_BANDWIDTH_Tracker available_send_window;
530 508
531 /** 509 /**
532 * How much downstream capacity of this peer has been reserved for 510 * Tracking bandwidth for receiving from this peer.
533 * our traffic? (Our clients can request that a certain amount of
534 * bandwidth is available for replies to them; this value is used to
535 * make sure that this reserved amount of bandwidth is actually
536 * available).
537 */ 511 */
538 long long available_recv_window; 512 struct GNUNET_BANDWIDTH_Tracker available_recv_window;
539 513
540 /** 514 /**
541 * How valueable were the messages of this peer recently? 515 * How valueable were the messages of this peer recently?
@@ -562,26 +536,26 @@ struct Neighbour
562 /** 536 /**
563 * Available bandwidth in for this peer (current target). 537 * Available bandwidth in for this peer (current target).
564 */ 538 */
565 uint32_t bpm_in; 539 struct GNUNET_BANDWIDTH_Value32NBO bw_in;
566 540
567 /** 541 /**
568 * Available bandwidth out for this peer (current target). 542 * Available bandwidth out for this peer (current target).
569 */ 543 */
570 uint32_t bpm_out; 544 struct GNUNET_BANDWIDTH_Value32NBO bw_out;
571 545
572 /** 546 /**
573 * Internal bandwidth limit set for this peer (initially 547 * Internal bandwidth limit set for this peer (initially typically
574 * typically set to "-1"). "bpm_out" is MAX of 548 * set to "-1"). Actual "bw_out" is MIN of
575 * "bpm_out_internal_limit" and "bpm_out_external_limit". 549 * "bpm_out_internal_limit" and "bw_out_external_limit".
576 */ 550 */
577 uint32_t bpm_out_internal_limit; 551 struct GNUNET_BANDWIDTH_Value32NBO bw_out_internal_limit;
578 552
579 /** 553 /**
580 * External bandwidth limit set for this peer by the 554 * External bandwidth limit set for this peer by the
581 * peer that we are communicating with. "bpm_out" is MAX of 555 * peer that we are communicating with. "bw_out" is MIN of
582 * "bpm_out_internal_limit" and "bpm_out_external_limit". 556 * "bw_out_internal_limit" and "bw_out_external_limit".
583 */ 557 */
584 uint32_t bpm_out_external_limit; 558 struct GNUNET_BANDWIDTH_Value32NBO bw_out_external_limit;
585 559
586 /** 560 /**
587 * What was our PING challenge number (for this peer)? 561 * What was our PING challenge number (for this peer)?
@@ -602,6 +576,7 @@ struct Neighbour
602 * Are we currently connected to this neighbour? 576 * Are we currently connected to this neighbour?
603 */ 577 */
604 int is_connected; 578 int is_connected;
579
605}; 580};
606 581
607 582
@@ -703,14 +678,15 @@ static unsigned long long preference_sum;
703static unsigned int neighbour_count; 678static unsigned int neighbour_count;
704 679
705/** 680/**
706 * How much inbound bandwidth are we supposed to be using? 681 * How much inbound bandwidth are we supposed to be using per second?
682 * FIXME: this value is not used!
707 */ 683 */
708static unsigned long long bandwidth_target_in; 684static unsigned long long bandwidth_target_in_bps;
709 685
710/** 686/**
711 * How much outbound bandwidth are we supposed to be using? 687 * How much outbound bandwidth are we supposed to be using per second?
712 */ 688 */
713static unsigned long long bandwidth_target_out; 689static unsigned long long bandwidth_target_out_bps;
714 690
715 691
716 692
@@ -743,50 +719,6 @@ update_preference_sum (unsigned long long inc)
743 719
744 720
745/** 721/**
746 * Recalculate the number of bytes we expect to
747 * receive or transmit in a given window.
748 *
749 * @param force force an update now (even if not much time has passed)
750 * @param window pointer to the byte counter (updated)
751 * @param ts pointer to the timestamp (updated)
752 * @param bpm number of bytes per minute that should
753 * be added to the window.
754 */
755static void
756update_window (int force,
757 long long *window,
758 struct GNUNET_TIME_Absolute *ts, unsigned int bpm)
759{
760 struct GNUNET_TIME_Relative since;
761 unsigned long long increment;
762
763 since = GNUNET_TIME_absolute_get_duration (*ts);
764 increment = (bpm * since.value) / 60 / 1000;
765#if DEBUG_CORE_QUOTA
766 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
767 "Updating window with %u bpm after %llu ms by %llu\n",
768 bpm,
769 (unsigned long long) since.value,
770 increment);
771#endif
772 if ( (force == GNUNET_NO) &&
773 (since.value < 60 * 1000) &&
774 (increment < 32 * 1024) )
775 {
776#if DEBUG_CORE_QUOTA
777 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
778 "Not updating window, change too small.\n");
779#endif
780 return; /* not even a minute has passed */
781 }
782 *ts = GNUNET_TIME_absolute_get ();
783 *window += increment;
784 if (*window > MAX_WINDOW_TIME * bpm)
785 *window = MAX_WINDOW_TIME * bpm;
786}
787
788
789/**
790 * Find the entry for the given neighbour. 722 * Find the entry for the given neighbour.
791 * 723 *
792 * @param peer identity of the neighbour 724 * @param peer identity of the neighbour
@@ -1004,8 +936,8 @@ handle_client_request_info (void *cls,
1004 const struct RequestInfoMessage *rcm; 936 const struct RequestInfoMessage *rcm;
1005 struct Neighbour *n; 937 struct Neighbour *n;
1006 struct ConfigurationInfoMessage cim; 938 struct ConfigurationInfoMessage cim;
1007 int want_reserv; 939 int32_t want_reserv;
1008 int got_reserv; 940 int32_t got_reserv;
1009 unsigned long long old_preference; 941 unsigned long long old_preference;
1010 struct GNUNET_SERVER_TransmitContext *tc; 942 struct GNUNET_SERVER_TransmitContext *tc;
1011 943
@@ -1019,32 +951,27 @@ handle_client_request_info (void *cls,
1019 if (n != NULL) 951 if (n != NULL)
1020 { 952 {
1021 want_reserv = ntohl (rcm->reserve_inbound); 953 want_reserv = ntohl (rcm->reserve_inbound);
1022 if (n->bpm_out_internal_limit != ntohl (rcm->limit_outbound_bpm)) 954 n->bw_out_internal_limit = rcm->limit_outbound;
1023 update_window (GNUNET_YES, 955 n->bw_out = GNUNET_BANDWIDTH_value_min (n->bw_out_internal_limit,
1024 &n->available_send_window, 956 n->bw_out_external_limit);
1025 &n->last_asw_update, 957 GNUNET_BANDWIDTH_tracker_update_quota (&n->available_recv_window,
1026 n->bpm_out); 958 n->bw_out);
1027 n->bpm_out_internal_limit = ntohl (rcm->limit_outbound_bpm);
1028 n->bpm_out = GNUNET_MIN (n->bpm_out_internal_limit,
1029 n->bpm_out_external_limit);
1030 if (want_reserv < 0) 959 if (want_reserv < 0)
1031 { 960 {
1032 got_reserv = want_reserv; 961 got_reserv = want_reserv;
1033 n->available_recv_window -= want_reserv;
1034 } 962 }
1035 else if (want_reserv > 0) 963 else if (want_reserv > 0)
1036 { 964 {
1037 update_window (GNUNET_NO, 965 if (GNUNET_BANDWIDTH_tracker_get_delay (&n->available_recv_window,
1038 &n->available_recv_window, 966 want_reserv).value == 0)
1039 &n->last_arw_update, n->bpm_in);
1040 if (n->available_recv_window < want_reserv)
1041 got_reserv = 0; /* all or nothing */
1042 else
1043 got_reserv = want_reserv; 967 got_reserv = want_reserv;
1044 n->available_recv_window -= got_reserv; 968 else
969 got_reserv = 0; /* all or nothing */
1045 } 970 }
1046 else 971 else
1047 got_reserv = 0; 972 got_reserv = 0;
973 GNUNET_BANDWIDTH_tracker_consume (&n->available_recv_window,
974 got_reserv);
1048 old_preference = n->current_preference; 975 old_preference = n->current_preference;
1049 n->current_preference += GNUNET_ntohll(rcm->preference_change); 976 n->current_preference += GNUNET_ntohll(rcm->preference_change);
1050 if (old_preference > n->current_preference) 977 if (old_preference > n->current_preference)
@@ -1056,13 +983,13 @@ handle_client_request_info (void *cls,
1056#if DEBUG_CORE_QUOTA 983#if DEBUG_CORE_QUOTA
1057 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 984 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1058 "Received reservation request for %d bytes for peer `%4s', reserved %d bytes\n", 985 "Received reservation request for %d bytes for peer `%4s', reserved %d bytes\n",
1059 want_reserv, 986 (int) want_reserv,
1060 GNUNET_i2s (&rcm->peer), 987 GNUNET_i2s (&rcm->peer),
1061 got_reserv); 988 (int) got_reserv);
1062#endif 989#endif
1063 cim.reserved_amount = htonl (got_reserv); 990 cim.reserved_amount = htonl (got_reserv);
1064 cim.bpm_in = htonl (n->bpm_in); 991 cim.bw_in = n->bw_in;
1065 cim.bpm_out = htonl (n->bpm_out); 992 cim.bw_out = n->bw_out;
1066 cim.preference = n->current_preference; 993 cim.preference = n->current_preference;
1067 } 994 }
1068 cim.header.size = htons (sizeof (struct ConfigurationInfoMessage)); 995 cim.header.size = htons (sizeof (struct ConfigurationInfoMessage));
@@ -1247,7 +1174,8 @@ notify_encrypted_transmit_ready (void *cls, size_t size, void *buf)
1247 GNUNET_assert (size >= m->size); 1174 GNUNET_assert (size >= m->size);
1248 memcpy (cbuf, &m[1], m->size); 1175 memcpy (cbuf, &m[1], m->size);
1249 ret = m->size; 1176 ret = m->size;
1250 n->available_send_window -= m->size; 1177 GNUNET_BANDWIDTH_tracker_consume (&n->available_send_window,
1178 m->size);
1251#if DEBUG_CORE 1179#if DEBUG_CORE
1252 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1180 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1253 "Copied message of type %u and size %u into transport buffer for `%4s'\n", 1181 "Copied message of type %u and size %u into transport buffer for `%4s'\n",
@@ -1444,9 +1372,9 @@ select_messages (struct Neighbour *n,
1444 unsigned int min_prio; 1372 unsigned int min_prio;
1445 struct GNUNET_TIME_Absolute t; 1373 struct GNUNET_TIME_Absolute t;
1446 struct GNUNET_TIME_Absolute now; 1374 struct GNUNET_TIME_Absolute now;
1447 uint64_t delta; 1375 struct GNUNET_TIME_Relative delta;
1448 uint64_t avail; 1376 uint64_t avail;
1449 unsigned long long slack; /* how long could we wait before missing deadlines? */ 1377 struct GNUNET_TIME_Relative slack; /* how long could we wait before missing deadlines? */
1450 size_t off; 1378 size_t off;
1451 int discard_low_prio; 1379 int discard_low_prio;
1452 unsigned int queue_size; 1380 unsigned int queue_size;
@@ -1472,18 +1400,13 @@ select_messages (struct Neighbour *n,
1472 min_prio = -1; 1400 min_prio = -1;
1473 discard_low_prio = GNUNET_NO; 1401 discard_low_prio = GNUNET_NO;
1474 /* calculate number of bytes available for transmission at time "t" */ 1402 /* calculate number of bytes available for transmission at time "t" */
1475 update_window (GNUNET_NO, 1403 avail = GNUNET_BANDWIDTH_tracker_get_available (&n->available_send_window);
1476 &n->available_send_window, 1404 t = now;
1477 &n->last_asw_update,
1478 n->bpm_out);
1479 avail = n->available_send_window;
1480 t = n->last_asw_update;
1481 /* how many bytes have we (hypothetically) scheduled so far */ 1405 /* how many bytes have we (hypothetically) scheduled so far */
1482 off = 0; 1406 off = 0;
1483 /* maximum time we can wait before transmitting anything 1407 /* maximum time we can wait before transmitting anything
1484 and still make all of our deadlines */ 1408 and still make all of our deadlines */
1485 slack = -1; 1409 slack = GNUNET_TIME_UNIT_FOREVER_REL;
1486
1487 pos = n->messages; 1410 pos = n->messages;
1488 /* note that we use "*2" here because we want to look 1411 /* note that we use "*2" here because we want to look
1489 a bit further into the future; much more makes no 1412 a bit further into the future; much more makes no
@@ -1499,14 +1422,17 @@ select_messages (struct Neighbour *n,
1499 } 1422 }
1500 if (discard_low_prio == GNUNET_NO) 1423 if (discard_low_prio == GNUNET_NO)
1501 { 1424 {
1502 delta = pos->deadline.value; 1425 delta = GNUNET_TIME_absolute_get_difference (t, pos->deadline);
1503 if (delta < t.value) 1426 if (delta.value > 0)
1504 delta = 0; 1427 {
1505 else 1428 // FIXME: HUH? Check!
1506 delta = t.value - delta; 1429 t = pos->deadline;
1507 avail += delta * n->bpm_out / 1000 / 60; 1430 avail += GNUNET_BANDWIDTH_value_get_available_until (n->bw_out,
1431 delta);
1432 }
1508 if (avail < pos->size) 1433 if (avail < pos->size)
1509 { 1434 {
1435 // FIXME: HUH? Check!
1510 discard_low_prio = GNUNET_YES; /* we could not schedule this one! */ 1436 discard_low_prio = GNUNET_YES; /* we could not schedule this one! */
1511 } 1437 }
1512 else 1438 else
@@ -1515,23 +1441,25 @@ select_messages (struct Neighbour *n,
1515 /* update slack, considering both its absolute deadline 1441 /* update slack, considering both its absolute deadline
1516 and relative deadlines caused by other messages 1442 and relative deadlines caused by other messages
1517 with their respective load */ 1443 with their respective load */
1518 slack = GNUNET_MIN (slack, avail / n->bpm_out); 1444 slack = GNUNET_TIME_relative_min (slack,
1445 GNUNET_BANDWIDTH_value_get_delay_for (n->bw_out,
1446 avail));
1519 if ( (pos->deadline.value < now.value) || 1447 if ( (pos->deadline.value < now.value) ||
1520 (GNUNET_YES == pos->got_slack) ) 1448 (GNUNET_YES == pos->got_slack) )
1521 { 1449 {
1522 slack = 0; 1450 slack = GNUNET_TIME_UNIT_ZERO;
1523 } 1451 }
1524 else 1452 else
1525 { 1453 {
1526 slack = 1454 slack =
1527 GNUNET_MIN (slack, pos->deadline.value - now.value); 1455 GNUNET_TIME_relative_min (slack,
1456 GNUNET_TIME_absolute_get_difference (now, pos->deadline));
1528 pos->got_slack = GNUNET_YES; 1457 pos->got_slack = GNUNET_YES;
1529 } 1458 }
1530 } 1459 }
1531 } 1460 }
1532
1533 off += pos->size; 1461 off += pos->size;
1534 t.value = GNUNET_MAX (pos->deadline.value, t.value); 1462 t = GNUNET_TIME_absolute_max (pos->deadline, t); // HUH? Check!
1535 if (pos->priority <= min_prio) 1463 if (pos->priority <= min_prio)
1536 { 1464 {
1537 /* update min for discard */ 1465 /* update min for discard */
@@ -1550,7 +1478,7 @@ select_messages (struct Neighbour *n,
1550 } 1478 }
1551 /* guard against sending "tiny" messages with large headers without 1479 /* guard against sending "tiny" messages with large headers without
1552 urgent deadlines */ 1480 urgent deadlines */
1553 if ( (slack > 1000) && 1481 if ( (slack.value > 1000) &&
1554 (size > 4 * off) && 1482 (size > 4 * off) &&
1555 (queue_size < MAX_PEER_QUEUE_SIZE / 2) ) 1483 (queue_size < MAX_PEER_QUEUE_SIZE / 2) )
1556 { 1484 {
@@ -1786,6 +1714,9 @@ set_key_retry_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1786{ 1714{
1787 struct Neighbour *n = cls; 1715 struct Neighbour *n = cls;
1788 1716
1717 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1718 "Retrying key transmission to `%4s'\n",
1719 GNUNET_i2s (&n->peer));
1789 n->retry_set_key_task = GNUNET_SCHEDULER_NO_TASK; 1720 n->retry_set_key_task = GNUNET_SCHEDULER_NO_TASK;
1790 n->set_key_retry_frequency = 1721 n->set_key_retry_frequency =
1791 GNUNET_TIME_relative_multiply (n->set_key_retry_frequency, 2); 1722 GNUNET_TIME_relative_multiply (n->set_key_retry_frequency, 2);
@@ -1901,13 +1832,13 @@ process_plaintext_neighbour_queue (struct Neighbour *n)
1901 } 1832 }
1902#if DEBUG_CORE_QUOTA 1833#if DEBUG_CORE_QUOTA
1903 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1834 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1904 "Sending %llu as new limit to peer `%4s'\n", 1835 "Sending %u b/s as new limit to peer `%4s'\n",
1905 (unsigned long long) n->bpm_in, 1836 (unsigned int) ntohl (n->bw_in.value__),
1906 GNUNET_i2s (&n->peer)); 1837 GNUNET_i2s (&n->peer));
1907#endif 1838#endif
1908 ph->iv_seed = htonl (GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, -1)); 1839 ph->iv_seed = htonl (GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, -1));
1909 ph->sequence_number = htonl (++n->last_sequence_number_sent); 1840 ph->sequence_number = htonl (++n->last_sequence_number_sent);
1910 ph->inbound_bpm_limit = htonl (n->bpm_in); 1841 ph->inbound_bw_limit = n->bw_in;
1911 ph->timestamp = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get ()); 1842 ph->timestamp = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get ());
1912 1843
1913 /* setup encryption message header */ 1844 /* setup encryption message header */
@@ -1998,10 +1929,10 @@ create_neighbour (const struct GNUNET_PeerIdentity *pid)
1998 n->encrypt_key_created = now; 1929 n->encrypt_key_created = now;
1999 n->last_activity = now; 1930 n->last_activity = now;
2000 n->set_key_retry_frequency = INITIAL_SET_KEY_RETRY_FREQUENCY; 1931 n->set_key_retry_frequency = INITIAL_SET_KEY_RETRY_FREQUENCY;
2001 n->bpm_in = GNUNET_CONSTANTS_DEFAULT_BPM_IN_OUT; 1932 n->bw_in = GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT;
2002 n->bpm_out = GNUNET_CONSTANTS_DEFAULT_BPM_IN_OUT; 1933 n->bw_out = GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT;
2003 n->bpm_out_internal_limit = (uint32_t) - 1; 1934 n->bw_out_internal_limit = GNUNET_BANDWIDTH_value_init ((uint32_t) - 1);
2004 n->bpm_out_external_limit = GNUNET_CONSTANTS_DEFAULT_BPM_IN_OUT; 1935 n->bw_out_external_limit = GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT;
2005 n->ping_challenge = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 1936 n->ping_challenge = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
2006 (uint32_t) - 1); 1937 (uint32_t) - 1);
2007 schedule_quota_update (n); 1938 schedule_quota_update (n);
@@ -2148,7 +2079,15 @@ static size_t
2148notify_transport_connect_done (void *cls, size_t size, void *buf) 2079notify_transport_connect_done (void *cls, size_t size, void *buf)
2149{ 2080{
2150 struct Neighbour *n = cls; 2081 struct Neighbour *n = cls;
2082
2151 n->th = NULL; 2083 n->th = NULL;
2084 if (buf == NULL)
2085 {
2086 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2087 _("Failed to connect to `%4s': transport failed to connect\n"),
2088 GNUNET_i2s (&n->peer));
2089 return 0;
2090 }
2152 send_key (n); 2091 send_key (n);
2153 return 0; 2092 return 0;
2154} 2093}
@@ -2170,6 +2109,12 @@ handle_client_request_connect (void *cls,
2170 struct Neighbour *n; 2109 struct Neighbour *n;
2171 struct GNUNET_TIME_Relative timeout; 2110 struct GNUNET_TIME_Relative timeout;
2172 2111
2112 if (0 == memcmp (&cm->peer, &my_identity, sizeof (struct GNUNET_PeerIdentity)))
2113 {
2114 GNUNET_break (0);
2115 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2116 return;
2117 }
2173 GNUNET_SERVER_receive_done (client, GNUNET_OK); 2118 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2174 n = find_neighbour (&cm->peer); 2119 n = find_neighbour (&cm->peer);
2175 if (n == NULL) 2120 if (n == NULL)
@@ -2541,7 +2486,7 @@ handle_ping (struct Neighbour *n, const struct PingMessage *m)
2541 me->priority = PONG_PRIORITY; 2486 me->priority = PONG_PRIORITY;
2542 me->size = sizeof (struct PongMessage); 2487 me->size = sizeof (struct PongMessage);
2543 tx.reserved = htonl (0); 2488 tx.reserved = htonl (0);
2544 tx.inbound_bpm_limit = htonl (n->bpm_in); 2489 tx.inbound_bw_limit = n->bw_in;
2545 tx.challenge = t.challenge; 2490 tx.challenge = t.challenge;
2546 tx.target = t.target; 2491 tx.target = t.target;
2547 tp = (struct PongMessage *) &me[1]; 2492 tp = (struct PongMessage *) &me[1];
@@ -2628,9 +2573,11 @@ handle_pong (struct Neighbour *n,
2628 return; 2573 return;
2629 case PEER_STATE_KEY_RECEIVED: 2574 case PEER_STATE_KEY_RECEIVED:
2630 n->status = PEER_STATE_KEY_CONFIRMED; 2575 n->status = PEER_STATE_KEY_CONFIRMED;
2631 n->bpm_out_external_limit = ntohl (t.inbound_bpm_limit); 2576 n->bw_out_external_limit = t.inbound_bw_limit;
2632 n->bpm_out = GNUNET_MIN (n->bpm_out_external_limit, 2577 n->bw_out = GNUNET_BANDWIDTH_value_min (n->bw_out_external_limit,
2633 n->bpm_out_internal_limit); 2578 n->bw_out_internal_limit);
2579 GNUNET_BANDWIDTH_tracker_update_quota (&n->available_send_window,
2580 n->bw_out);
2634#if DEBUG_CORE 2581#if DEBUG_CORE
2635 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2582 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2636 "Confirmed key via `%s' message for peer `%4s'\n", 2583 "Confirmed key via `%s' message for peer `%4s'\n",
@@ -3087,22 +3034,18 @@ handle_encrypted_message (struct Neighbour *n,
3087 } 3034 }
3088 3035
3089 /* process decrypted message(s) */ 3036 /* process decrypted message(s) */
3090 if (n->bpm_out_external_limit != ntohl (pt->inbound_bpm_limit))
3091 {
3092 update_window (GNUNET_YES,
3093 &n->available_send_window,
3094 &n->last_asw_update,
3095 n->bpm_out);
3096#if DEBUG_CORE_QUOTA 3037#if DEBUG_CORE_QUOTA
3097 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 3038 if (n->bw_out_external_limit.value__ != pt->inbound_bw_limit.value__)
3098 "Received %llu as new inbound limit for peer `%4s'\n", 3039 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3099 (unsigned long long) ntohl (pt->inbound_bpm_limit), 3040 "Received %u b/s as new inbound limit for peer `%4s'\n",
3100 GNUNET_i2s (&n->peer)); 3041 (unsigned int) ntohl (pt->inbound_bw_limit.value__),
3101#endif 3042 GNUNET_i2s (&n->peer));
3102 } 3043#endif
3103 n->bpm_out_external_limit = ntohl (pt->inbound_bpm_limit); 3044 n->bw_out_external_limit = pt->inbound_bw_limit;
3104 n->bpm_out = GNUNET_MIN (n->bpm_out_external_limit, 3045 n->bw_out = GNUNET_BANDWIDTH_value_min (n->bw_out_external_limit,
3105 n->bpm_out_internal_limit); 3046 n->bw_out_internal_limit);
3047 GNUNET_BANDWIDTH_tracker_update_quota (&n->available_send_window,
3048 n->bw_out);
3106 n->last_activity = GNUNET_TIME_absolute_get (); 3049 n->last_activity = GNUNET_TIME_absolute_get ();
3107 off = sizeof (struct EncryptedMessage); 3050 off = sizeof (struct EncryptedMessage);
3108 deliver_messages (n, buf, size, off); 3051 deliver_messages (n, buf, size, off);
@@ -3247,12 +3190,12 @@ neighbour_quota_update (void *cls,
3247 const struct GNUNET_SCHEDULER_TaskContext *tc) 3190 const struct GNUNET_SCHEDULER_TaskContext *tc)
3248{ 3191{
3249 struct Neighbour *n = cls; 3192 struct Neighbour *n = cls;
3250 uint32_t q_in; 3193 struct GNUNET_BANDWIDTH_Value32NBO q_in;
3251 double pref_rel; 3194 double pref_rel;
3252 double share; 3195 double share;
3253 unsigned long long distributable; 3196 unsigned long long distributable;
3254 uint32_t qin_ms; 3197 uint64_t need_per_peer;
3255 uint32_t qout_ms; 3198 uint64_t need_per_second;
3256 3199
3257 n->quota_update_task = GNUNET_SCHEDULER_NO_TASK; 3200 n->quota_update_task = GNUNET_SCHEDULER_NO_TASK;
3258 /* calculate relative preference among all neighbours; 3201 /* calculate relative preference among all neighbours;
@@ -3267,43 +3210,45 @@ neighbour_quota_update (void *cls,
3267 { 3210 {
3268 pref_rel = n->current_preference / preference_sum; 3211 pref_rel = n->current_preference / preference_sum;
3269 } 3212 }
3270 3213 need_per_peer = GNUNET_BANDWIDTH_value_get_available_until (MIN_BANDWIDTH_PER_PEER,
3214 GNUNET_TIME_UNIT_SECONDS);
3215 need_per_second = need_per_peer * neighbour_count;
3271 distributable = 0; 3216 distributable = 0;
3272 if (bandwidth_target_out > neighbour_count * MIN_BPM_PER_PEER) 3217 if (bandwidth_target_out_bps > need_per_second)
3273 distributable = bandwidth_target_out - neighbour_count * MIN_BPM_PER_PEER; 3218 distributable = bandwidth_target_out_bps - need_per_second;
3274 share = distributable * pref_rel; 3219 share = distributable * pref_rel;
3275 q_in = MIN_BPM_PER_PEER + (unsigned long long) share; 3220 if (share + need_per_peer > ( (uint32_t)-1))
3221 q_in = GNUNET_BANDWIDTH_value_init ((uint32_t) -1);
3222 else
3223 q_in = GNUNET_BANDWIDTH_value_init (need_per_peer + (uint32_t) share);
3276 /* check if we want to disconnect for good due to inactivity */ 3224 /* check if we want to disconnect for good due to inactivity */
3277 if ( (GNUNET_TIME_absolute_get_duration (n->last_activity).value > GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT.value) && 3225 if ( (GNUNET_TIME_absolute_get_duration (n->last_activity).value > GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT.value) &&
3278 (GNUNET_TIME_absolute_get_duration (n->time_established).value > GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT.value) ) 3226 (GNUNET_TIME_absolute_get_duration (n->time_established).value > GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT.value) )
3279 { 3227 {
3280#if DEBUG_CORE 3228#if DEBUG_CORE
3281 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 3229 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3282 "Forcing disconnect of `%4s' due to inactivity (?).\n", 3230 "Forcing disconnect of `%4s' due to inactivity (?).\n",
3283 GNUNET_i2s (&n->peer)); 3231 GNUNET_i2s (&n->peer));
3284#endif 3232#endif
3285 q_in = 0; /* force disconnect */ 3233 q_in = GNUNET_BANDWIDTH_value_init (0); /* force disconnect */
3286 } 3234 }
3287#if DEBUG_CORE_QUOTA 3235#if DEBUG_CORE_QUOTA
3288 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 3236 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3289 "Current quota for `%4s' is %llu in (old: %llu) / %llu out (%llu internal)\n", 3237 "Current quota for `%4s' is %u/%llu b/s in (old: %u b/s) / %u out (%u internal)\n",
3290 GNUNET_i2s (&n->peer), 3238 GNUNET_i2s (&n->peer),
3291 (unsigned long long) q_in, 3239 (unsigned int) ntohl (q_in.value__),
3292 (unsigned long long) n->bpm_in, 3240 bandwidth_target_out_bps,
3293 (unsigned long long) n->bpm_out, 3241 (unsigned int) ntohl (n->bw_in.value__),
3294 (unsigned long long) n->bpm_out_internal_limit); 3242 (unsigned int) ntohl (n->bw_out.value__),
3295#endif 3243 (unsigned int) ntohl (n->bw_out_internal_limit.value__));
3296 if ( (n->bpm_in + MIN_BPM_CHANGE < q_in) || 3244#endif
3297 (n->bpm_in - MIN_BPM_CHANGE > q_in) ) 3245 if (n->bw_in.value__ != q_in.value__)
3298 { 3246 {
3299 n->bpm_in = q_in; 3247 n->bw_in = q_in;
3300 /* need to convert to bytes / ms, rounding up! */
3301 qin_ms = (q_in == 0) ? 0 : 1 + q_in / 60000;
3302 qout_ms = (n->bpm_out == 0) ? 0 : 1 + n->bpm_out / 60000;
3303 GNUNET_TRANSPORT_set_quota (transport, 3248 GNUNET_TRANSPORT_set_quota (transport,
3304 &n->peer, 3249 &n->peer,
3305 qin_ms, 3250 n->bw_in,
3306 qout_ms, 3251 n->bw_out,
3307 GNUNET_TIME_UNIT_FOREVER_REL, 3252 GNUNET_TIME_UNIT_FOREVER_REL,
3308 NULL, NULL); 3253 NULL, NULL);
3309 } 3254 }
@@ -3348,8 +3293,12 @@ handle_transport_notify_connect (void *cls,
3348 n->is_connected = GNUNET_YES; 3293 n->is_connected = GNUNET_YES;
3349 n->last_latency = latency; 3294 n->last_latency = latency;
3350 n->last_distance = distance; 3295 n->last_distance = distance;
3351 n->last_asw_update = now; 3296 GNUNET_BANDWIDTH_tracker_init (&n->available_send_window,
3352 n->last_arw_update = now; 3297 n->bw_out,
3298 MAX_WINDOW_TIME_S);
3299 GNUNET_BANDWIDTH_tracker_init (&n->available_recv_window,
3300 n->bw_in,
3301 MAX_WINDOW_TIME_S);
3353#if DEBUG_CORE 3302#if DEBUG_CORE
3354 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 3303 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3355 "Received connection from `%4s'.\n", 3304 "Received connection from `%4s'.\n",
@@ -3445,11 +3394,6 @@ run (void *cls,
3445 struct GNUNET_SERVER_Handle *serv, 3394 struct GNUNET_SERVER_Handle *serv,
3446 const struct GNUNET_CONFIGURATION_Handle *c) 3395 const struct GNUNET_CONFIGURATION_Handle *c)
3447{ 3396{
3448#if 0
3449 unsigned long long qin;
3450 unsigned long long qout;
3451 unsigned long long tneigh;
3452#endif
3453 char *keyfile; 3397 char *keyfile;
3454 3398
3455 sched = s; 3399 sched = s;
@@ -3460,12 +3404,12 @@ run (void *cls,
3460 GNUNET_CONFIGURATION_get_value_number (c, 3404 GNUNET_CONFIGURATION_get_value_number (c,
3461 "CORE", 3405 "CORE",
3462 "TOTAL_QUOTA_IN", 3406 "TOTAL_QUOTA_IN",
3463 &bandwidth_target_in)) || 3407 &bandwidth_target_in_bps)) ||
3464 (GNUNET_OK != 3408 (GNUNET_OK !=
3465 GNUNET_CONFIGURATION_get_value_number (c, 3409 GNUNET_CONFIGURATION_get_value_number (c,
3466 "CORE", 3410 "CORE",
3467 "TOTAL_QUOTA_OUT", 3411 "TOTAL_QUOTA_OUT",
3468 &bandwidth_target_out)) || 3412 &bandwidth_target_out_bps)) ||
3469 (GNUNET_OK != 3413 (GNUNET_OK !=
3470 GNUNET_CONFIGURATION_get_value_filename (c, 3414 GNUNET_CONFIGURATION_get_value_filename (c,
3471 "GNUNETD", 3415 "GNUNETD",
diff --git a/src/fs/gnunet-service-fs.c b/src/fs/gnunet-service-fs.c
index ac9290948..8fd47a006 100644
--- a/src/fs/gnunet-service-fs.c
+++ b/src/fs/gnunet-service-fs.c
@@ -1217,8 +1217,8 @@ static void
1217target_reservation_cb (void *cls, 1217target_reservation_cb (void *cls,
1218 const struct 1218 const struct
1219 GNUNET_PeerIdentity * peer, 1219 GNUNET_PeerIdentity * peer,
1220 unsigned int bpm_in, 1220 struct GNUNET_BANDWIDTH_Value32NBO bpm_in,
1221 unsigned int bpm_out, 1221 struct GNUNET_BANDWIDTH_Value32NBO bpm_out,
1222 int amount, 1222 int amount,
1223 uint64_t preference) 1223 uint64_t preference)
1224{ 1224{
@@ -1440,7 +1440,7 @@ forward_request_task (void *cls,
1440 pr->irc = GNUNET_CORE_peer_change_preference (sched, cfg, 1440 pr->irc = GNUNET_CORE_peer_change_preference (sched, cfg,
1441 &psc.target, 1441 &psc.target,
1442 GNUNET_CONSTANTS_SERVICE_TIMEOUT, 1442 GNUNET_CONSTANTS_SERVICE_TIMEOUT,
1443 (uint32_t) -1 /* no limit */, 1443 GNUNET_BANDWIDTH_value_init ((uint32_t) -1 /* no limit */),
1444 DBLOCK_SIZE, 1444 DBLOCK_SIZE,
1445 (uint64_t) cp->inc_preference, 1445 (uint64_t) cp->inc_preference,
1446 &target_reservation_cb, 1446 &target_reservation_cb,
diff --git a/src/include/Makefile.am b/src/include/Makefile.am
index 39fb2f0f5..605cbbe1e 100644
--- a/src/include/Makefile.am
+++ b/src/include/Makefile.am
@@ -13,6 +13,7 @@ nodist_gnunetinclude_HEADERS = \
13 13
14gnunetinclude_HEADERS = \ 14gnunetinclude_HEADERS = \
15 gnunet_arm_service.h \ 15 gnunet_arm_service.h \
16 gnunet_bandwidth_lib.h \
16 gnunet_bio_lib.h \ 17 gnunet_bio_lib.h \
17 gnunet_client_lib.h \ 18 gnunet_client_lib.h \
18 gnunet_common.h \ 19 gnunet_common.h \
diff --git a/src/include/gnunet_constants.h b/src/include/gnunet_constants.h
index eb8addf5f..035cc60b9 100644
--- a/src/include/gnunet_constants.h
+++ b/src/include/gnunet_constants.h
@@ -35,13 +35,15 @@ extern "C"
35#endif 35#endif
36#endif 36#endif
37 37
38#include "gnunet_bandwidth_lib.h"
39
38/** 40/**
39 * Amount of bytes per minute (in/out) to assume initially (before 41 * Bandwidth (in/out) to assume initially (before either peer has
40 * either peer has communicated any particular preference). Should be 42 * communicated any particular preference). Should be rather low; set
41 * rather low; set so that at least one maximum-size message can be 43 * so that at least one maximum-size message can be send roughly once
42 * send each minute. 44 * per minute.
43 */ 45 */
44#define GNUNET_CONSTANTS_DEFAULT_BPM_IN_OUT GNUNET_SERVER_MAX_MESSAGE_SIZE 46#define GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT GNUNET_BANDWIDTH_value_init (1024)
45 47
46/** 48/**
47 * After how long do we consider a connection to a peer dead 49 * After how long do we consider a connection to a peer dead
diff --git a/src/include/gnunet_core_service.h b/src/include/gnunet_core_service.h
index af0a4eaa9..47b8d6f98 100644
--- a/src/include/gnunet_core_service.h
+++ b/src/include/gnunet_core_service.h
@@ -281,8 +281,8 @@ typedef void
281 (*GNUNET_CORE_PeerConfigurationInfoCallback) (void *cls, 281 (*GNUNET_CORE_PeerConfigurationInfoCallback) (void *cls,
282 const struct 282 const struct
283 GNUNET_PeerIdentity * peer, 283 GNUNET_PeerIdentity * peer,
284 unsigned int bpm_in, 284 struct GNUNET_BANDWIDTH_Value32NBO bpm_in,
285 unsigned int bpm_out, 285 struct GNUNET_BANDWIDTH_Value32NBO bpm_out,
286 int amount, 286 int amount,
287 uint64_t preference); 287 uint64_t preference);
288 288
@@ -302,11 +302,11 @@ struct GNUNET_CORE_InformationRequestContext;
302 * @param peer identifies the peer 302 * @param peer identifies the peer
303 * @param timeout after how long should we give up (and call "info" with NULL 303 * @param timeout after how long should we give up (and call "info" with NULL
304 * for "peer" to signal an error)? 304 * for "peer" to signal an error)?
305 * @param bpm_out set to the current bandwidth limit (sending) for this peer, 305 * @param bw_out set to the current bandwidth limit (sending) for this peer,
306 * caller should set "bpm_out" to "-1" to avoid changing 306 * caller should set "bpm_out" to "-1" to avoid changing
307 * the current value; otherwise "bpm_out" will be lowered to 307 * the current value; otherwise "bw_out" will be lowered to
308 * the specified value; passing a pointer to "0" can be used to force 308 * the specified value; passing a pointer to "0" can be used to force
309 * us to disconnect from the peer; "bpm_out" might not increase 309 * us to disconnect from the peer; "bw_out" might not increase
310 * as specified since the upper bound is generally 310 * as specified since the upper bound is generally
311 * determined by the other peer! 311 * determined by the other peer!
312 * @param amount reserve N bytes for receiving, negative 312 * @param amount reserve N bytes for receiving, negative
@@ -324,7 +324,7 @@ GNUNET_CORE_peer_change_preference (struct GNUNET_SCHEDULER_Handle *sched,
324 const struct GNUNET_CONFIGURATION_Handle *cfg, 324 const struct GNUNET_CONFIGURATION_Handle *cfg,
325 const struct GNUNET_PeerIdentity *peer, 325 const struct GNUNET_PeerIdentity *peer,
326 struct GNUNET_TIME_Relative timeout, 326 struct GNUNET_TIME_Relative timeout,
327 uint32_t bpm_out, 327 struct GNUNET_BANDWIDTH_Value32NBO bw_out,
328 int32_t amount, 328 int32_t amount,
329 uint64_t preference, 329 uint64_t preference,
330 GNUNET_CORE_PeerConfigurationInfoCallback info, 330 GNUNET_CORE_PeerConfigurationInfoCallback info,
diff --git a/src/include/gnunet_transport_service.h b/src/include/gnunet_transport_service.h
index 7a3ccbf7b..47d4334bb 100644
--- a/src/include/gnunet_transport_service.h
+++ b/src/include/gnunet_transport_service.h
@@ -35,6 +35,7 @@ extern "C"
35#endif 35#endif
36#endif 36#endif
37 37
38#include "gnunet_bandwidth_lib.h"
38#include "gnunet_configuration_lib.h" 39#include "gnunet_configuration_lib.h"
39#include "gnunet_crypto_lib.h" 40#include "gnunet_crypto_lib.h"
40#include "gnunet_connection_lib.h" 41#include "gnunet_connection_lib.h"
@@ -153,8 +154,8 @@ void GNUNET_TRANSPORT_disconnect (struct GNUNET_TRANSPORT_Handle *handle);
153 * 154 *
154 * @param handle connection to transport service 155 * @param handle connection to transport service
155 * @param target who's bandwidth quota is being changed 156 * @param target who's bandwidth quota is being changed
156 * @param quota_in incoming bandwidth quota in bytes per ms 157 * @param quota_in incoming bandwidth quota
157 * @param quota_out outgoing bandwidth quota in bytes per ms 158 * @param quota_out outgoing bandwidth quota
158 * @param timeout how long to wait until signaling failure if 159 * @param timeout how long to wait until signaling failure if
159 * we can not communicate the quota change 160 * we can not communicate the quota change
160 * @param cont continuation to call when done, will be called 161 * @param cont continuation to call when done, will be called
@@ -164,8 +165,8 @@ void GNUNET_TRANSPORT_disconnect (struct GNUNET_TRANSPORT_Handle *handle);
164void 165void
165GNUNET_TRANSPORT_set_quota (struct GNUNET_TRANSPORT_Handle *handle, 166GNUNET_TRANSPORT_set_quota (struct GNUNET_TRANSPORT_Handle *handle,
166 const struct GNUNET_PeerIdentity *target, 167 const struct GNUNET_PeerIdentity *target,
167 uint32_t quota_in, 168 struct GNUNET_BANDWIDTH_Value32NBO quota_in,
168 uint32_t quota_out, 169 struct GNUNET_BANDWIDTH_Value32NBO quota_out,
169 struct GNUNET_TIME_Relative timeout, 170 struct GNUNET_TIME_Relative timeout,
170 GNUNET_SCHEDULER_Task cont, void *cont_cls); 171 GNUNET_SCHEDULER_Task cont, void *cont_cls);
171 172
diff --git a/src/include/gnunet_util_lib.h b/src/include/gnunet_util_lib.h
index 1c5e1d7a1..e0a5b0774 100644
--- a/src/include/gnunet_util_lib.h
+++ b/src/include/gnunet_util_lib.h
@@ -37,6 +37,7 @@ extern "C"
37#endif 37#endif
38 38
39#include "gnunet_common.h" 39#include "gnunet_common.h"
40#include "gnunet_bandwidth_lib.h"
40#include "gnunet_bio_lib.h" 41#include "gnunet_bio_lib.h"
41#include "gnunet_client_lib.h" 42#include "gnunet_client_lib.h"
42#include "gnunet_configuration_lib.h" 43#include "gnunet_configuration_lib.h"
diff --git a/src/topology/gnunet-daemon-topology.c b/src/topology/gnunet-daemon-topology.c
index 6ae4d8210..7f761360d 100644
--- a/src/topology/gnunet-daemon-topology.c
+++ b/src/topology/gnunet-daemon-topology.c
@@ -832,6 +832,11 @@ consider_for_advertising (const struct GNUNET_HELLO_Message *hello)
832 struct PeerList *pos; 832 struct PeerList *pos;
833 uint16_t size; 833 uint16_t size;
834 834
835 GNUNET_break (GNUNET_OK == GNUNET_HELLO_get_id (hello, &pid));
836 if (0 == memcmp (&pid,
837 &my_identity,
838 sizeof (struct GNUNET_PeerIdentity)))
839 return; /* that's me! */
835 have_address = GNUNET_NO; 840 have_address = GNUNET_NO;
836 GNUNET_HELLO_iterate_addresses (hello, 841 GNUNET_HELLO_iterate_addresses (hello,
837 GNUNET_NO, 842 GNUNET_NO,
@@ -839,7 +844,6 @@ consider_for_advertising (const struct GNUNET_HELLO_Message *hello)
839 &have_address); 844 &have_address);
840 if (GNUNET_NO == have_address) 845 if (GNUNET_NO == have_address)
841 return; /* no point in advertising this one... */ 846 return; /* no point in advertising this one... */
842 GNUNET_break (GNUNET_OK == GNUNET_HELLO_get_id (hello, &pid));
843 peer = find_peer (&pid); 847 peer = find_peer (&pid);
844 if (peer == NULL) 848 if (peer == NULL)
845 peer = make_peer (&pid, hello, GNUNET_NO); 849 peer = make_peer (&pid, hello, GNUNET_NO);
@@ -1098,13 +1102,24 @@ read_friends_file (const struct GNUNET_CONFIGURATION_Handle *cfg)
1098 } 1102 }
1099 else 1103 else
1100 { 1104 {
1101 entries_found++; 1105 if (0 != memcmp (&pid,
1102 fl = make_peer (&pid, 1106 &my_identity,
1103 NULL, 1107 sizeof (struct GNUNET_PeerIdentity)))
1104 GNUNET_YES); 1108 {
1105 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1109 entries_found++;
1106 _("Found friend `%s' in configuration\n"), 1110 fl = make_peer (&pid,
1107 GNUNET_i2s (&fl->id)); 1111 NULL,
1112 GNUNET_YES);
1113 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1114 _("Found friend `%s' in configuration\n"),
1115 GNUNET_i2s (&fl->id));
1116 }
1117 else
1118 {
1119 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1120 _("Found myself `%s' in friend list (useless, ignored)\n"),
1121 GNUNET_i2s (&fl->id));
1122 }
1108 } 1123 }
1109 pos = pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded); 1124 pos = pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded);
1110 while ((pos < frstat.st_size) && isspace (data[pos])) 1125 while ((pos < frstat.st_size) && isspace (data[pos]))
diff --git a/src/topology/test_gnunet_service_topology_data.conf b/src/topology/test_gnunet_service_topology_data.conf
index 588134b8a..a7cf18955 100644
--- a/src/topology/test_gnunet_service_topology_data.conf
+++ b/src/topology/test_gnunet_service_topology_data.conf
@@ -8,6 +8,7 @@ PORT = 2664
8[transport] 8[transport]
9PORT = 2665 9PORT = 2665
10PLUGINS = tcp 10PLUGINS = tcp
11DEBUG = YES
11#PREFIX = xterm -e xterm -T transport -e gdb -x cmd --args 12#PREFIX = xterm -e xterm -T transport -e gdb -x cmd --args
12#PREFIX = valgrind --tool=memcheck --log-file=logs%p 13#PREFIX = valgrind --tool=memcheck --log-file=logs%p
13 14
diff --git a/src/transport/gnunet-service-transport.c b/src/transport/gnunet-service-transport.c
index b99955807..3566c229c 100644
--- a/src/transport/gnunet-service-transport.c
+++ b/src/transport/gnunet-service-transport.c
@@ -79,7 +79,7 @@
79 * How often must a peer violate bandwidth quotas before we start 79 * How often must a peer violate bandwidth quotas before we start
80 * to simply drop its messages? 80 * to simply drop its messages?
81 */ 81 */
82#define QUOTA_VIOLATION_DROP_THRESHOLD 100 82#define QUOTA_VIOLATION_DROP_THRESHOLD 10
83 83
84/** 84/**
85 * How long until a HELLO verification attempt should time out? 85 * How long until a HELLO verification attempt should time out?
@@ -99,7 +99,7 @@
99/** 99/**
100 * How often will we re-validate for latency information 100 * How often will we re-validate for latency information
101 */ 101 */
102#define TRANSPORT_DEFAULT_REVALIDATION GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15) 102#define TRANSPORT_DEFAULT_REVALIDATION GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60)
103 103
104/** 104/**
105 * Priority to use for PONG messages. 105 * Priority to use for PONG messages.
@@ -456,9 +456,9 @@ struct NeighbourList
456 struct GNUNET_TIME_Absolute peer_timeout; 456 struct GNUNET_TIME_Absolute peer_timeout;
457 457
458 /** 458 /**
459 * At what time did we reset last_received last? 459 * Tracker for inbound bandwidth.
460 */ 460 */
461 struct GNUNET_TIME_Absolute last_quota_update; 461 struct GNUNET_BANDWIDTH_Tracker in_tracker;
462 462
463 /** 463 /**
464 * The latency we have seen for this particular address for 464 * The latency we have seen for this particular address for
@@ -474,22 +474,6 @@ struct NeighbourList
474 struct GNUNET_TIME_Relative latency; 474 struct GNUNET_TIME_Relative latency;
475 475
476 /** 476 /**
477 * DV distance to this peer (1 if no DV is used).
478 */
479 uint32_t distance;
480
481 /**
482 * How many bytes have we received since the "last_quota_update"
483 * timestamp?
484 */
485 uint64_t last_received;
486
487 /**
488 * Global quota for inbound traffic for the neighbour in bytes/ms.
489 */
490 uint32_t quota_in;
491
492 /**
493 * How often has the other peer (recently) violated the 477 * How often has the other peer (recently) violated the
494 * inbound traffic limit? Incremented by 10 per violation, 478 * inbound traffic limit? Incremented by 10 per violation,
495 * decremented by 1 per non-violation (for each 479 * decremented by 1 per non-violation (for each
@@ -498,6 +482,11 @@ struct NeighbourList
498 unsigned int quota_violation_count; 482 unsigned int quota_violation_count;
499 483
500 /** 484 /**
485 * DV distance to this peer (1 if no DV is used).
486 */
487 uint32_t distance;
488
489 /**
501 * Have we seen an PONG from this neighbour in the past (and 490 * Have we seen an PONG from this neighbour in the past (and
502 * not had a disconnect since)? 491 * not had a disconnect since)?
503 */ 492 */
@@ -899,56 +888,6 @@ find_transport (const char *short_name)
899 888
900 889
901/** 890/**
902 * Update the quota values for the given neighbour now.
903 *
904 * @param n neighbour to update
905 * @param force GNUNET_YES to force recalculation now
906 */
907static void
908update_quota (struct NeighbourList *n,
909 int force)
910{
911 struct GNUNET_TIME_Absolute now;
912 unsigned long long delta;
913 uint64_t allowed;
914 uint64_t remaining;
915
916 now = GNUNET_TIME_absolute_get ();
917 delta = now.value - n->last_quota_update.value;
918 allowed = n->quota_in * delta;
919 if ( (delta < MIN_QUOTA_REFRESH_TIME) &&
920 (!force) &&
921 (allowed < 32 * 1024) )
922 return; /* too early, not enough data */
923 if (n->last_received < allowed)
924 {
925 remaining = allowed - n->last_received;
926 if (n->quota_in > 0)
927 remaining /= n->quota_in;
928 else
929 remaining = 0;
930 if (remaining > MAX_BANDWIDTH_CARRY)
931 remaining = MAX_BANDWIDTH_CARRY;
932 n->last_received = 0;
933 n->last_quota_update = now;
934 n->last_quota_update.value -= remaining;
935 if (n->quota_violation_count > 0)
936 n->quota_violation_count--;
937 }
938 else
939 {
940 n->last_received -= allowed;
941 n->last_quota_update = now;
942 if (n->last_received > allowed)
943 {
944 /* much more than the allowed rate! */
945 n->quota_violation_count += 10;
946 }
947 }
948}
949
950
951/**
952 * Function called to notify a client about the socket being ready to 891 * Function called to notify a client about the socket being ready to
953 * queue more data. "buf" will be NULL and "size" zero if the socket 892 * queue more data. "buf" will be NULL and "size" zero if the socket
954 * was closed for writing in the meantime. 893 * was closed for writing in the meantime.
@@ -1274,6 +1213,8 @@ try_transmission_to_peer (struct NeighbourList *neighbour)
1274 GNUNET_i2s (&mq->neighbour_id), 1213 GNUNET_i2s (&mq->neighbour_id),
1275 timeout.value); 1214 timeout.value);
1276#endif 1215#endif
1216 /* FIXME: might want to trigger peerinfo lookup here
1217 (unless that's already pending...) */
1277 return; 1218 return;
1278 } 1219 }
1279 GNUNET_CONTAINER_DLL_remove (neighbour->messages_head, 1220 GNUNET_CONTAINER_DLL_remove (neighbour->messages_head,
@@ -1788,12 +1729,14 @@ add_validated_address (void *cls,
1788 max); 1729 max);
1789} 1730}
1790 1731
1791static void send_periodic_ping(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); 1732
1733static void send_periodic_ping(void *cls,
1734 const struct GNUNET_SCHEDULER_TaskContext *tc);
1735
1792 1736
1793/** 1737/**
1794 * Iterator over hash map entries. Checks if the given 1738 * Iterator over hash map entries. Checks if the given validation
1795 * validation entry is for the same challenge as what 1739 * entry is for the same challenge as what is given in the PONG.
1796 * is given in the PONG.
1797 * 1740 *
1798 * @param cls the 'struct TransportPongMessage*' 1741 * @param cls the 'struct TransportPongMessage*'
1799 * @param key peer identity 1742 * @param key peer identity
@@ -1843,19 +1786,28 @@ check_pending_validation (void *cls,
1843 n = find_neighbour (&target); 1786 n = find_neighbour (&target);
1844 if (n != NULL) 1787 if (n != NULL)
1845 { 1788 {
1846 fal = add_peer_address (n, ve->transport_name, 1789 fal = add_peer_address (n,
1790 ve->transport_name,
1847 ve->addr, 1791 ve->addr,
1848 ve->addrlen); 1792 ve->addrlen);
1849 fal->expires = GNUNET_TIME_relative_to_absolute (HELLO_ADDRESS_EXPIRATION); 1793 fal->expires = GNUNET_TIME_relative_to_absolute (HELLO_ADDRESS_EXPIRATION);
1850 fal->validated = GNUNET_YES; 1794 fal->validated = GNUNET_YES;
1851 fal->latency = GNUNET_TIME_absolute_get_duration (ve->send_time); 1795 fal->latency = GNUNET_TIME_absolute_get_duration (ve->send_time);
1852
1853 periodic_validation_context = GNUNET_malloc(sizeof(struct PeriodicValidationContext)); 1796 periodic_validation_context = GNUNET_malloc(sizeof(struct PeriodicValidationContext));
1854 periodic_validation_context->foreign_address = fal; 1797 periodic_validation_context->foreign_address = fal;
1855 periodic_validation_context->transport = strdup(ve->transport_name); 1798 periodic_validation_context->transport = strdup(ve->transport_name);
1856 memcpy(&periodic_validation_context->publicKey, &ve->publicKey, sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded)); 1799 memcpy(&periodic_validation_context->publicKey,
1857 1800 &ve->publicKey,
1858 fal->revalidate_task = GNUNET_SCHEDULER_add_delayed(sched, TRANSPORT_DEFAULT_REVALIDATION, &send_periodic_ping, periodic_validation_context); 1801 sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
1802 /* FIXME: this causes all of the revalidation PINGs for the same HELLO
1803 to be transmitted in bulk, which is not nice; also,
1804 triggering these HERE means that revalidations do NOT happen AT ALL
1805 for HELLOs a previous instance of this process validated (since
1806 there is no "initial" validation PING => no revalidation => BUG! */
1807 fal->revalidate_task = GNUNET_SCHEDULER_add_delayed(sched,
1808 TRANSPORT_DEFAULT_REVALIDATION,
1809 &send_periodic_ping,
1810 periodic_validation_context);
1859 if (n->latency.value == GNUNET_TIME_UNIT_FOREVER_REL.value) 1811 if (n->latency.value == GNUNET_TIME_UNIT_FOREVER_REL.value)
1860 n->latency = fal->latency; 1812 n->latency = fal->latency;
1861 else 1813 else
@@ -1985,11 +1937,12 @@ setup_new_neighbour (const struct GNUNET_PeerIdentity *peer)
1985 n->next = neighbours; 1937 n->next = neighbours;
1986 neighbours = n; 1938 neighbours = n;
1987 n->id = *peer; 1939 n->id = *peer;
1988 n->last_quota_update = GNUNET_TIME_absolute_get ();
1989 n->peer_timeout = 1940 n->peer_timeout =
1990 GNUNET_TIME_relative_to_absolute 1941 GNUNET_TIME_relative_to_absolute
1991 (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT); 1942 (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
1992 n->quota_in = (GNUNET_CONSTANTS_DEFAULT_BPM_IN_OUT + 59999) / (60 * 1000); 1943 GNUNET_BANDWIDTH_tracker_init (&n->in_tracker,
1944 GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT,
1945 MAX_BANDWIDTH_CARRY_S);
1993 tp = plugins; 1946 tp = plugins;
1994 while (tp != NULL) 1947 while (tp != NULL)
1995 { 1948 {
@@ -2098,6 +2051,7 @@ timeout_hello_validation (void *cls, const struct GNUNET_SCHEDULER_TaskContext *
2098 GNUNET_free (va); 2051 GNUNET_free (va);
2099} 2052}
2100 2053
2054
2101/** 2055/**
2102 * Check if the given address is already being validated; if not, 2056 * Check if the given address is already being validated; if not,
2103 * append the given address to the list of entries that are being be 2057 * append the given address to the list of entries that are being be
@@ -2229,7 +2183,9 @@ rerun_validation (void *cls,
2229 * that gets discarded on the other side instead of initiating 2183 * that gets discarded on the other side instead of initiating
2230 * a flood. 2184 * a flood.
2231 */ 2185 */
2232static void send_periodic_ping(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 2186static void
2187send_periodic_ping (void *cls,
2188 const struct GNUNET_SCHEDULER_TaskContext *tc)
2233{ 2189{
2234 struct PeriodicValidationContext *periodic_validation_context = cls; 2190 struct PeriodicValidationContext *periodic_validation_context = cls;
2235 2191
@@ -2239,8 +2195,11 @@ static void send_periodic_ping(void *cls, const struct GNUNET_SCHEDULER_TaskCont
2239 GNUNET_free(periodic_validation_context); 2195 GNUNET_free(periodic_validation_context);
2240 return; /* We have been shutdown, don't do anything! */ 2196 return; /* We have been shutdown, don't do anything! */
2241 } 2197 }
2242 2198 rerun_validation(&periodic_validation_context->publicKey,
2243 rerun_validation(&periodic_validation_context->publicKey, periodic_validation_context->transport, periodic_validation_context->foreign_address->expires, periodic_validation_context->foreign_address->addr, periodic_validation_context->foreign_address->addrlen); 2199 periodic_validation_context->transport,
2200 periodic_validation_context->foreign_address->expires,
2201 periodic_validation_context->foreign_address->addr,
2202 periodic_validation_context->foreign_address->addrlen);
2244 GNUNET_free(periodic_validation_context->transport); 2203 GNUNET_free(periodic_validation_context->transport);
2245 GNUNET_free(periodic_validation_context); 2204 GNUNET_free(periodic_validation_context);
2246} 2205}
@@ -2367,8 +2326,6 @@ run_validation (void *cls,
2367} 2326}
2368 2327
2369 2328
2370
2371
2372/** 2329/**
2373 * Add the given address to the list of foreign addresses 2330 * Add the given address to the list of foreign addresses
2374 * available for the given peer (check for duplicates). 2331 * available for the given peer (check for duplicates).
@@ -2388,7 +2345,9 @@ add_to_foreign_address_list (void *cls,
2388{ 2345{
2389 struct NeighbourList *n = cls; 2346 struct NeighbourList *n = cls;
2390 struct ForeignAddressList *fal; 2347 struct ForeignAddressList *fal;
2348 int try;
2391 2349
2350 try = GNUNET_NO;
2392 fal = find_peer_address (n, tname, addr, addrlen); 2351 fal = find_peer_address (n, tname, addr, addrlen);
2393 if (fal == NULL) 2352 if (fal == NULL)
2394 { 2353 {
@@ -2401,12 +2360,15 @@ add_to_foreign_address_list (void *cls,
2401 expiration.value); 2360 expiration.value);
2402#endif 2361#endif
2403 fal = add_peer_address (n, tname, addr, addrlen); 2362 fal = add_peer_address (n, tname, addr, addrlen);
2363 try = GNUNET_YES;
2404 } 2364 }
2405 if (fal == NULL) 2365 if (fal == NULL)
2406 return GNUNET_OK; 2366 return GNUNET_OK;
2407 fal->expires = GNUNET_TIME_absolute_max (expiration, 2367 fal->expires = GNUNET_TIME_absolute_max (expiration,
2408 fal->expires); 2368 fal->expires);
2409 fal->validated = GNUNET_YES; 2369 fal->validated = GNUNET_YES;
2370 if (try == GNUNET_YES)
2371 try_transmission_to_peer (n);
2410 return GNUNET_OK; 2372 return GNUNET_OK;
2411} 2373}
2412 2374
@@ -2524,14 +2486,13 @@ process_hello (struct TransportPlugin *plugin,
2524 GNUNET_CRYPTO_hash (&publicKey, 2486 GNUNET_CRYPTO_hash (&publicKey,
2525 sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), 2487 sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
2526 &target.hashPubKey); 2488 &target.hashPubKey);
2527#if DEBUG_TRANSPORT 2489#if DEBUG_TRANSPORT > 1
2528 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2490 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2529 "Processing `%s' message for `%4s' of size %u\n", 2491 "Processing `%s' message for `%4s' of size %u\n",
2530 "HELLO", 2492 "HELLO",
2531 GNUNET_i2s (&target), 2493 GNUNET_i2s (&target),
2532 GNUNET_HELLO_size(hello)); 2494 GNUNET_HELLO_size(hello));
2533#endif 2495#endif
2534
2535 chvc = GNUNET_malloc (sizeof (struct CheckHelloValidatedContext) + hsize); 2496 chvc = GNUNET_malloc (sizeof (struct CheckHelloValidatedContext) + hsize);
2536 chvc->hello = (const struct GNUNET_HELLO_Message *) &chvc[1]; 2497 chvc->hello = (const struct GNUNET_HELLO_Message *) &chvc[1];
2537 memcpy (&chvc[1], hello, hsize); 2498 memcpy (&chvc[1], hello, hsize);
@@ -2740,47 +2701,6 @@ handle_ping(void *cls, const struct GNUNET_MessageHeader *message,
2740 2701
2741 2702
2742/** 2703/**
2743 * Calculate how long we should delay reading from the TCP socket to
2744 * ensure that we stay within our bandwidth limits (push back).
2745 *
2746 * @param n for which neighbour should this be calculated
2747 * @return how long to delay receiving more data
2748 */
2749static struct GNUNET_TIME_Relative
2750calculate_throttle_delay (struct NeighbourList *n)
2751{
2752 struct GNUNET_TIME_Relative ret;
2753 struct GNUNET_TIME_Absolute now;
2754 uint64_t del;
2755 uint64_t avail;
2756 uint64_t excess;
2757
2758 now = GNUNET_TIME_absolute_get ();
2759 del = now.value - n->last_quota_update.value;
2760 if (del > MAX_BANDWIDTH_CARRY)
2761 {
2762 update_quota (n, GNUNET_YES);
2763 del = now.value - n->last_quota_update.value;
2764 GNUNET_assert (del <= MAX_BANDWIDTH_CARRY);
2765 }
2766 if (n->quota_in == 0)
2767 n->quota_in = 1; /* avoid divison by zero */
2768 avail = del * n->quota_in;
2769 if (avail > n->last_received)
2770 return GNUNET_TIME_UNIT_ZERO; /* can receive right now */
2771 excess = n->last_received - avail;
2772 ret.value = excess / n->quota_in;
2773 if (ret.value > 0)
2774 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2775 "Throttling read (%llu bytes excess at %llu b/ms), waiting %llums before reading more.\n",
2776 (unsigned long long) excess,
2777 (unsigned long long) n->quota_in,
2778 (unsigned long long) ret.value);
2779 return ret;
2780}
2781
2782
2783/**
2784 * Function called by the plugin for each received message. 2704 * Function called by the plugin for each received message.
2785 * Update data volumes, possibly notify plugins about 2705 * Update data volumes, possibly notify plugins about
2786 * reducing the rate at which they read from the socket 2706 * reducing the rate at which they read from the socket
@@ -2809,11 +2729,11 @@ plugin_env_receive (void *cls, const struct GNUNET_PeerIdentity *peer,
2809 struct ForeignAddressList *peer_address; 2729 struct ForeignAddressList *peer_address;
2810 uint16_t msize; 2730 uint16_t msize;
2811 struct NeighbourList *n; 2731 struct NeighbourList *n;
2732 struct GNUNET_TIME_Relative ret;
2812 2733
2813 n = find_neighbour (peer); 2734 n = find_neighbour (peer);
2814 if (n == NULL) 2735 if (n == NULL)
2815 n = setup_new_neighbour (peer); 2736 n = setup_new_neighbour (peer);
2816 update_quota (n, GNUNET_NO);
2817 service_context = n->plugins; 2737 service_context = n->plugins;
2818 while ((service_context != NULL) && (plugin != service_context->plugin)) 2738 while ((service_context != NULL) && (plugin != service_context->plugin))
2819 service_context = service_context->next; 2739 service_context = service_context->next;
@@ -2838,7 +2758,7 @@ plugin_env_receive (void *cls, const struct GNUNET_PeerIdentity *peer,
2838 (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT); 2758 (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
2839 } 2759 }
2840 /* update traffic received amount ... */ 2760 /* update traffic received amount ... */
2841 msize = ntohs (message->size); 2761 msize = ntohs (message->size);
2842 n->distance = distance; 2762 n->distance = distance;
2843 n->peer_timeout = 2763 n->peer_timeout =
2844 GNUNET_TIME_relative_to_absolute 2764 GNUNET_TIME_relative_to_absolute
@@ -2855,7 +2775,8 @@ plugin_env_receive (void *cls, const struct GNUNET_PeerIdentity *peer,
2855 GNUNET_log (GNUNET_ERROR_TYPE_WARNING | 2775 GNUNET_log (GNUNET_ERROR_TYPE_WARNING |
2856 GNUNET_ERROR_TYPE_BULK, 2776 GNUNET_ERROR_TYPE_BULK,
2857 _ 2777 _
2858 ("Dropping incoming message due to repeated bandwidth quota violations (total of %u).\n"), 2778 ("Dropping incoming message due to repeated bandwidth quota (%u b/s) violations (total of %u).\n"),
2779 n->in_tracker.available_bytes_per_s__,
2859 n->quota_violation_count); 2780 n->quota_violation_count);
2860 return GNUNET_TIME_UNIT_MINUTES; /* minimum penalty, likely ignored (UDP...) */ 2781 return GNUNET_TIME_UNIT_MINUTES; /* minimum penalty, likely ignored (UDP...) */
2861 } 2782 }
@@ -2876,6 +2797,11 @@ plugin_env_receive (void *cls, const struct GNUNET_PeerIdentity *peer,
2876 "Received message of type %u from `%4s', sending to all clients.\n", 2797 "Received message of type %u from `%4s', sending to all clients.\n",
2877 ntohs (message->type), GNUNET_i2s (peer)); 2798 ntohs (message->type), GNUNET_i2s (peer));
2878#endif 2799#endif
2800 if (GNUNET_YES == GNUNET_BANDWIDTH_tracker_consume (&n->in_tracker,
2801 msize))
2802 n->quota_violation_count++;
2803 else
2804 n->quota_violation_count = 0; /* back within limits */
2879 /* transmit message to all clients */ 2805 /* transmit message to all clients */
2880 im = GNUNET_malloc (sizeof (struct InboundMessage) + msize); 2806 im = GNUNET_malloc (sizeof (struct InboundMessage) + msize);
2881 im->header.size = htons (sizeof (struct InboundMessage) + msize); 2807 im->header.size = htons (sizeof (struct InboundMessage) + msize);
@@ -2892,7 +2818,14 @@ plugin_env_receive (void *cls, const struct GNUNET_PeerIdentity *peer,
2892 GNUNET_free (im); 2818 GNUNET_free (im);
2893 } 2819 }
2894 } 2820 }
2895 return calculate_throttle_delay (n); 2821 ret = GNUNET_BANDWIDTH_tracker_get_delay (&n->in_tracker, 0);
2822 if (ret.value > 0)
2823 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2824 "Throttling read (%llu bytes excess at %u b/s), waiting %llums before reading more.\n",
2825 (unsigned long long) n->in_tracker.consumption_since_last_update__,
2826 (unsigned int) n->in_tracker.available_bytes_per_s__,
2827 (unsigned long long) ret.value);
2828 return ret;
2896} 2829}
2897 2830
2898 2831
@@ -3058,7 +2991,6 @@ handle_set_quota (void *cls,
3058 const struct QuotaSetMessage *qsm = 2991 const struct QuotaSetMessage *qsm =
3059 (const struct QuotaSetMessage *) message; 2992 (const struct QuotaSetMessage *) message;
3060 struct NeighbourList *n; 2993 struct NeighbourList *n;
3061 uint32_t qin;
3062 2994
3063 n = find_neighbour (&qsm->peer); 2995 n = find_neighbour (&qsm->peer);
3064 if (n == NULL) 2996 if (n == NULL)
@@ -3066,16 +2998,16 @@ handle_set_quota (void *cls,
3066 GNUNET_SERVER_receive_done (client, GNUNET_OK); 2998 GNUNET_SERVER_receive_done (client, GNUNET_OK);
3067 return; 2999 return;
3068 } 3000 }
3069 qin = ntohl (qsm->quota_in);
3070#if DEBUG_TRANSPORT 3001#if DEBUG_TRANSPORT
3071 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 3002 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3072 "Received `%s' request (new quota %u, old quota %u) from client for peer `%4s'\n", 3003 "Received `%s' request (new quota %u, old quota %u) from client for peer `%4s'\n",
3073 "SET_QUOTA", qin, n->quota_in, GNUNET_i2s (&qsm->peer)); 3004 "SET_QUOTA",
3005 (unsigned int) ntohl (qsm->quota.value__),
3006 (unsigned int) n->in_tracker.available_bytes_per_s__,
3007 GNUNET_i2s (&qsm->peer));
3074#endif 3008#endif
3075 update_quota (n, GNUNET_YES); 3009 GNUNET_BANDWIDTH_tracker_update_quota (&n->in_tracker,
3076 if (n->quota_in < qin) 3010 qsm->quota);
3077 n->last_quota_update = GNUNET_TIME_absolute_get ();
3078 n->quota_in = qin;
3079 GNUNET_SERVER_receive_done (client, GNUNET_OK); 3011 GNUNET_SERVER_receive_done (client, GNUNET_OK);
3080} 3012}
3081 3013
diff --git a/src/transport/plugin_transport_tcp.c b/src/transport/plugin_transport_tcp.c
index 9b6200b80..3b198841a 100644
--- a/src/transport/plugin_transport_tcp.c
+++ b/src/transport/plugin_transport_tcp.c
@@ -39,7 +39,7 @@
39#include "plugin_transport.h" 39#include "plugin_transport.h"
40#include "transport.h" 40#include "transport.h"
41 41
42#define DEBUG_TCP GNUNET_NO 42#define DEBUG_TCP GNUNET_YES
43 43
44/** 44/**
45 * How long until we give up on transmitting the welcome message? 45 * How long until we give up on transmitting the welcome message?
diff --git a/src/transport/test_transport_api.c b/src/transport/test_transport_api.c
index 4895e758a..e159b054e 100644
--- a/src/transport/test_transport_api.c
+++ b/src/transport/test_transport_api.c
@@ -226,7 +226,6 @@ exchange_hello_last (void *cls,
226 struct PeerContext *me = cls; 226 struct PeerContext *me = cls;
227 227
228 GNUNET_TRANSPORT_get_hello_cancel (p2.th, &exchange_hello_last, me); 228 GNUNET_TRANSPORT_get_hello_cancel (p2.th, &exchange_hello_last, me);
229
230 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 229 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
231 "Exchanging HELLO with peer (%p)!\n", cls); 230 "Exchanging HELLO with peer (%p)!\n", cls);
232 GNUNET_assert (ok >= 3); 231 GNUNET_assert (ok >= 3);
@@ -266,7 +265,6 @@ exchange_hello (void *cls,
266 "Received HELLO size %d\n", GNUNET_HELLO_size((const struct GNUNET_HELLO_Message *)message)); 265 "Received HELLO size %d\n", GNUNET_HELLO_size((const struct GNUNET_HELLO_Message *)message));
267 266
268 GNUNET_TRANSPORT_offer_hello (p2.th, message); 267 GNUNET_TRANSPORT_offer_hello (p2.th, message);
269
270 GNUNET_TRANSPORT_get_hello (p2.th, &exchange_hello_last, &p2); 268 GNUNET_TRANSPORT_get_hello (p2.th, &exchange_hello_last, &p2);
271} 269}
272 270
diff --git a/src/transport/transport.h b/src/transport/transport.h
index 993efac7c..d66b87b35 100644
--- a/src/transport/transport.h
+++ b/src/transport/transport.h
@@ -30,15 +30,15 @@
30#include "gnunet_time_lib.h" 30#include "gnunet_time_lib.h"
31#include "gnunet_transport_service.h" 31#include "gnunet_transport_service.h"
32 32
33#define DEBUG_TRANSPORT GNUNET_NO 33#define DEBUG_TRANSPORT GNUNET_YES
34#define DEBUG_TRANSPORT_TIMEOUT GNUNET_NO 34#define DEBUG_TRANSPORT_TIMEOUT GNUNET_YES
35#define DEBUG_TRANSPORT_DISCONNECT GNUNET_NO 35#define DEBUG_TRANSPORT_DISCONNECT GNUNET_YES
36 36
37/** 37/**
38 * For how long do we allow unused bandwidth 38 * For how long do we allow unused bandwidth
39 * from the past to carry over into the future? (in ms) 39 * from the past to carry over into the future? (in seconds)
40 */ 40 */
41#define MAX_BANDWIDTH_CARRY 5000 41#define MAX_BANDWIDTH_CARRY_S 5
42 42
43/** 43/**
44 * How often do we (at most) do a full quota 44 * How often do we (at most) do a full quota
@@ -102,9 +102,9 @@ struct DisconnectInfoMessage
102 102
103 103
104/** 104/**
105 * Message used to set a particular bandwidth quota. Send 105 * Message used to set a particular bandwidth quota. Send TO the
106 * TO the service to set an incoming quota, send FROM the 106 * service to set an incoming quota, send FROM the service to update
107 * service to update an outgoing quota. 107 * an outgoing quota.
108 */ 108 */
109struct QuotaSetMessage 109struct QuotaSetMessage
110{ 110{
@@ -115,10 +115,9 @@ struct QuotaSetMessage
115 struct GNUNET_MessageHeader header; 115 struct GNUNET_MessageHeader header;
116 116
117 /** 117 /**
118 * Quota in bytes per ms, 0 to drop everything; 118 * Quota.
119 * in network byte order.
120 */ 119 */
121 uint32_t quota_in GNUNET_PACKED; 120 struct GNUNET_BANDWIDTH_Value32NBO quota;
122 121
123 /** 122 /**
124 * About which peer are we talking here? 123 * About which peer are we talking here?
diff --git a/src/transport/transport_api.c b/src/transport/transport_api.c
index 26106ae48..7328dc95d 100644
--- a/src/transport/transport_api.c
+++ b/src/transport/transport_api.c
@@ -24,6 +24,7 @@
24 * @author Christian Grothoff 24 * @author Christian Grothoff
25 */ 25 */
26#include "platform.h" 26#include "platform.h"
27#include "gnunet_bandwidth_lib.h"
27#include "gnunet_client_lib.h" 28#include "gnunet_client_lib.h"
28#include "gnunet_constants.h" 29#include "gnunet_constants.h"
29#include "gnunet_container_lib.h" 30#include "gnunet_container_lib.h"
@@ -215,20 +216,9 @@ struct NeighbourList
215 struct GNUNET_PeerIdentity id; 216 struct GNUNET_PeerIdentity id;
216 217
217 /** 218 /**
218 * At what time did we reset last_sent last? 219 * Outbound bandwidh tracker.
219 */ 220 */
220 struct GNUNET_TIME_Absolute last_quota_update; 221 struct GNUNET_BANDWIDTH_Tracker out_tracker;
221
222 /**
223 * How many bytes have we sent since the "last_quota_update"
224 * timestamp?
225 */
226 uint64_t last_sent;
227
228 /**
229 * Quota for outbound traffic to the neighbour in bytes/ms.
230 */
231 uint32_t quota_out;
232 222
233 /** 223 /**
234 * Set to GNUNET_NO if we are currently allowed to accept a 224 * Set to GNUNET_NO if we are currently allowed to accept a
@@ -417,41 +407,6 @@ quota_transmit_ready (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
417 407
418 408
419/** 409/**
420 * Update the quota values for the given neighbour now.
421 *
422 * @param n neighbour to update
423 */
424static void
425update_quota (struct NeighbourList *n)
426{
427 struct GNUNET_TIME_Relative delta;
428 uint64_t allowed;
429 uint64_t remaining;
430
431 delta = GNUNET_TIME_absolute_get_duration (n->last_quota_update);
432 allowed = delta.value * n->quota_out;
433 if (n->last_sent < allowed)
434 {
435 remaining = allowed - n->last_sent;
436 if (n->quota_out > 0)
437 remaining /= n->quota_out;
438 else
439 remaining = 0;
440 if (remaining > MAX_BANDWIDTH_CARRY)
441 remaining = MAX_BANDWIDTH_CARRY;
442 n->last_sent = 0;
443 n->last_quota_update = GNUNET_TIME_absolute_get ();
444 n->last_quota_update.value -= remaining;
445 }
446 else
447 {
448 n->last_sent -= allowed;
449 n->last_quota_update = GNUNET_TIME_absolute_get ();
450 }
451}
452
453
454/**
455 * Figure out which transmission to a peer can be done right now. 410 * Figure out which transmission to a peer can be done right now.
456 * If none can, schedule a task to call 'schedule_transmission' 411 * If none can, schedule a task to call 'schedule_transmission'
457 * whenever a peer transmission can be done in the future and 412 * whenever a peer transmission can be done in the future and
@@ -470,7 +425,6 @@ schedule_peer_transmission (struct GNUNET_TRANSPORT_Handle *h)
470 struct NeighbourList *next; 425 struct NeighbourList *next;
471 struct GNUNET_TIME_Relative retry_time; 426 struct GNUNET_TIME_Relative retry_time;
472 struct GNUNET_TIME_Relative duration; 427 struct GNUNET_TIME_Relative duration;
473 uint64_t available;
474 428
475 if (h->quota_task != GNUNET_SCHEDULER_NO_TASK) 429 if (h->quota_task != GNUNET_SCHEDULER_NO_TASK)
476 { 430 {
@@ -487,47 +441,38 @@ schedule_peer_transmission (struct GNUNET_TRANSPORT_Handle *h)
487 if (n->transmit_stage != TS_QUEUED) 441 if (n->transmit_stage != TS_QUEUED)
488 continue; /* not eligible */ 442 continue; /* not eligible */
489 th = &n->transmit_handle; 443 th = &n->transmit_handle;
444 GNUNET_break (n == th->neighbour);
490 /* check outgoing quota */ 445 /* check outgoing quota */
491 duration = GNUNET_TIME_absolute_get_duration (n->last_quota_update); 446 duration = GNUNET_BANDWIDTH_tracker_get_delay (&n->out_tracker,
492 if (duration.value > MIN_QUOTA_REFRESH_TIME) 447 th->notify_size - sizeof (struct OutboundMessage));
493 { 448 if (th->timeout.value < duration.value)
494 update_quota (n);
495 duration = GNUNET_TIME_absolute_get_duration (n->last_quota_update);
496 }
497 available = duration.value * n->quota_out;
498 if (available < n->last_sent + th->notify_size)
499 { 449 {
500 /* calculate how much bandwidth we'd still need to 450 /* signal timeout! */
501 accumulate and based on that how long we'll have
502 to wait... */
503 available = n->last_sent + th->notify_size - available;
504 duration = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS,
505 available / n->quota_out);
506 if (duration.value == 0)
507 duration = GNUNET_TIME_UNIT_MILLISECONDS;
508 if (th->timeout.value <
509 GNUNET_TIME_relative_to_absolute (duration).value)
510 {
511 /* signal timeout! */
512#if DEBUG_TRANSPORT 451#if DEBUG_TRANSPORT
513 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 452 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
514 "Would need %llu ms before bandwidth is available for delivery to `%4s', that is too long. Signaling timeout.\n", 453 "Would need %llu ms before bandwidth is available for delivery to `%4s', that is too long. Signaling timeout.\n",
515 duration.value, GNUNET_i2s (&n->id)); 454 duration.value,
455 GNUNET_i2s (&n->id));
516#endif 456#endif
517 if (th->notify_delay_task != GNUNET_SCHEDULER_NO_TASK) 457 if (th->notify_delay_task != GNUNET_SCHEDULER_NO_TASK)
518 { 458 {
519 GNUNET_SCHEDULER_cancel (h->sched, th->notify_delay_task); 459 GNUNET_SCHEDULER_cancel (h->sched, th->notify_delay_task);
520 th->notify_delay_task = GNUNET_SCHEDULER_NO_TASK; 460 th->notify_delay_task = GNUNET_SCHEDULER_NO_TASK;
521 } 461 }
522 n->transmit_stage = TS_NEW; 462 n->transmit_stage = TS_NEW;
523 if (NULL != th->notify) 463 if (NULL != th->notify)
524 GNUNET_assert (0 == th->notify (th->notify_cls, 0, NULL)); 464 GNUNET_assert (0 == th->notify (th->notify_cls, 0, NULL));
525 continue; 465 continue;
526 } 466 }
467 if (duration.value > 0)
468 {
527#if DEBUG_TRANSPORT 469#if DEBUG_TRANSPORT
528 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 470 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
529 "Need more bandwidth, delaying delivery to `%4s' by %llu ms\n", 471 "Need more bandwidth (%u b/s allowed, %u b needed), delaying delivery to `%4s' by %llu ms\n",
530 GNUNET_i2s (&n->id), duration.value); 472 (unsigned int) n->out_tracker.available_bytes_per_s__,
473 (unsigned int) th->notify_size - sizeof (struct OutboundMessage),
474 GNUNET_i2s (&n->id),
475 duration.value);
531#endif 476#endif
532 retry_time = GNUNET_TIME_relative_min (retry_time, 477 retry_time = GNUNET_TIME_relative_min (retry_time,
533 duration); 478 duration);
@@ -536,9 +481,9 @@ schedule_peer_transmission (struct GNUNET_TRANSPORT_Handle *h)
536#if DEBUG_TRANSPORT 481#if DEBUG_TRANSPORT
537 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 482 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
538 "Have %u bytes of bandwidth available for transmission to `%4s' right now\n", 483 "Have %u bytes of bandwidth available for transmission to `%4s' right now\n",
539 th->notify_size, 484 th->notify_size - sizeof (struct OutboundMessage),
540 GNUNET_i2s (&n->id)); 485 GNUNET_i2s (&n->id));
541#endif 486#endif
542 if ( (ret == NULL) || 487 if ( (ret == NULL) ||
543 (ret->priority < th->priority) ) 488 (ret->priority < th->priority) )
544 ret = th; 489 ret = th;
@@ -630,6 +575,13 @@ transport_notify_ready (void *cls, size_t size, void *buf)
630 size - sizeof (struct OutboundMessage), 575 size - sizeof (struct OutboundMessage),
631 &cbuf[ret + sizeof (struct OutboundMessage)]); 576 &cbuf[ret + sizeof (struct OutboundMessage)]);
632 GNUNET_assert (mret <= size - sizeof (struct OutboundMessage)); 577 GNUNET_assert (mret <= size - sizeof (struct OutboundMessage));
578#if DEBUG_TRANSPORT
579 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
580 "Message of %u bytes with timeout %llums constructed for `%4s'\n",
581 (unsigned int) mret,
582 (unsigned long long) GNUNET_TIME_absolute_get_remaining (th->timeout).value,
583 GNUNET_i2s (&n->id));
584#endif
633 if (mret != 0) 585 if (mret != 0)
634 { 586 {
635 obm.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SEND); 587 obm.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SEND);
@@ -640,6 +592,7 @@ transport_notify_ready (void *cls, size_t size, void *buf)
640 memcpy (&cbuf[ret], &obm, sizeof (struct OutboundMessage)); 592 memcpy (&cbuf[ret], &obm, sizeof (struct OutboundMessage));
641 ret += (mret + sizeof (struct OutboundMessage)); 593 ret += (mret + sizeof (struct OutboundMessage));
642 size -= (mret + sizeof (struct OutboundMessage)); 594 size -= (mret + sizeof (struct OutboundMessage));
595 GNUNET_BANDWIDTH_tracker_consume (&n->out_tracker, mret);
643 } 596 }
644 else 597 else
645 { 598 {
@@ -799,7 +752,7 @@ struct SetQuotaContext
799 752
800 struct GNUNET_TIME_Absolute timeout; 753 struct GNUNET_TIME_Absolute timeout;
801 754
802 uint32_t quota_in; 755 struct GNUNET_BANDWIDTH_Value32NBO quota_in;
803}; 756};
804 757
805 758
@@ -836,7 +789,7 @@ send_set_quota (void *cls, size_t size, void *buf)
836 msg = buf; 789 msg = buf;
837 msg->header.size = htons (sizeof (struct QuotaSetMessage)); 790 msg->header.size = htons (sizeof (struct QuotaSetMessage));
838 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SET_QUOTA); 791 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SET_QUOTA);
839 msg->quota_in = htonl (sqc->quota_in); 792 msg->quota = sqc->quota_in;
840 memcpy (&msg->peer, &sqc->target, sizeof (struct GNUNET_PeerIdentity)); 793 memcpy (&msg->peer, &sqc->target, sizeof (struct GNUNET_PeerIdentity));
841 if (sqc->cont != NULL) 794 if (sqc->cont != NULL)
842 GNUNET_SCHEDULER_add_continuation (sqc->handle->sched, 795 GNUNET_SCHEDULER_add_continuation (sqc->handle->sched,
@@ -865,8 +818,8 @@ send_set_quota (void *cls, size_t size, void *buf)
865void 818void
866GNUNET_TRANSPORT_set_quota (struct GNUNET_TRANSPORT_Handle *handle, 819GNUNET_TRANSPORT_set_quota (struct GNUNET_TRANSPORT_Handle *handle,
867 const struct GNUNET_PeerIdentity *target, 820 const struct GNUNET_PeerIdentity *target,
868 uint32_t quota_in, 821 struct GNUNET_BANDWIDTH_Value32NBO quota_in,
869 uint32_t quota_out, 822 struct GNUNET_BANDWIDTH_Value32NBO quota_out,
870 struct GNUNET_TIME_Relative timeout, 823 struct GNUNET_TIME_Relative timeout,
871 GNUNET_SCHEDULER_Task cont, void *cont_cls) 824 GNUNET_SCHEDULER_Task cont, void *cont_cls)
872{ 825{
@@ -876,10 +829,14 @@ GNUNET_TRANSPORT_set_quota (struct GNUNET_TRANSPORT_Handle *handle,
876 n = neighbour_find (handle, target); 829 n = neighbour_find (handle, target);
877 if (n != NULL) 830 if (n != NULL)
878 { 831 {
879 update_quota (n); 832 if (ntohl (quota_out.value__) != n->out_tracker.available_bytes_per_s__)
880 if (n->quota_out < quota_out) 833 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
881 n->last_quota_update = GNUNET_TIME_absolute_get (); 834 "Quota changed from %u to %u for peer `%s'\n",
882 n->quota_out = quota_out; 835 (unsigned int) n->out_tracker.available_bytes_per_s__,
836 (unsigned int) ntohl (quota_out.value__),
837 GNUNET_i2s (target));
838 GNUNET_BANDWIDTH_tracker_update_quota (&n->out_tracker,
839 quota_out);
883 } 840 }
884 sqc = GNUNET_malloc (sizeof (struct SetQuotaContext)); 841 sqc = GNUNET_malloc (sizeof (struct SetQuotaContext));
885 sqc->handle = handle; 842 sqc->handle = handle;
@@ -1247,9 +1204,10 @@ neighbour_add (struct GNUNET_TRANSPORT_Handle *h,
1247#endif 1204#endif
1248 n = GNUNET_malloc (sizeof (struct NeighbourList)); 1205 n = GNUNET_malloc (sizeof (struct NeighbourList));
1249 n->id = *pid; 1206 n->id = *pid;
1250 n->last_quota_update = GNUNET_TIME_absolute_get (); 1207 GNUNET_BANDWIDTH_tracker_init (&n->out_tracker,
1208 GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT,
1209 MAX_BANDWIDTH_CARRY_S);
1251 n->next = h->neighbours; 1210 n->next = h->neighbours;
1252 n->quota_out = GNUNET_CONSTANTS_DEFAULT_BPM_IN_OUT;
1253 n->h = h; 1211 n->h = h;
1254 h->neighbours = n; 1212 h->neighbours = n;
1255 return n; 1213 return n;
@@ -1688,8 +1646,9 @@ GNUNET_TRANSPORT_notify_transmit_ready (struct GNUNET_TRANSPORT_Handle
1688 } 1646 }
1689#if DEBUG_TRANSPORT 1647#if DEBUG_TRANSPORT
1690 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1648 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1691 "Asking transport service for transmission of %u bytes to peer `%4s'.\n", 1649 "Asking transport service for transmission of %u bytes to peer `%4s' within %llu ms.\n",
1692 size, GNUNET_i2s (target)); 1650 size, GNUNET_i2s (target),
1651 (unsigned long long) timeout.value);
1693#endif 1652#endif
1694 n = neighbour_find (handle, target); 1653 n = neighbour_find (handle, target);
1695 if (n == NULL) 1654 if (n == NULL)