aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBart Polot <bart@net.in.tum.de>2013-07-13 10:15:16 +0000
committerBart Polot <bart@net.in.tum.de>2013-07-13 10:15:16 +0000
commit1a8ad09983f69db13cc992311cbf1320caca4d67 (patch)
treeb5387ab4411f1be2f13b63f05fbfbbf959df8568 /src
parentc82adc2479b9144ab5aec6a1631d669385219856 (diff)
downloadgnunet-1a8ad09983f69db13cc992311cbf1320caca4d67.tar.gz
gnunet-1a8ad09983f69db13cc992311cbf1320caca4d67.zip
- initital implementation of bitfield ACK-ing of future messages
Diffstat (limited to 'src')
-rw-r--r--src/mesh/gnunet-service-mesh.c159
1 files changed, 154 insertions, 5 deletions
diff --git a/src/mesh/gnunet-service-mesh.c b/src/mesh/gnunet-service-mesh.c
index 62c3553b1..1de719be8 100644
--- a/src/mesh/gnunet-service-mesh.c
+++ b/src/mesh/gnunet-service-mesh.c
@@ -2063,13 +2063,28 @@ static void
2063tunnel_send_fwd_data_ack (struct MeshTunnel *t) 2063tunnel_send_fwd_data_ack (struct MeshTunnel *t)
2064{ 2064{
2065 struct GNUNET_MESH_DataACK msg; 2065 struct GNUNET_MESH_DataACK msg;
2066 struct MeshTunnelReliability *rel;
2067 struct MeshReliableMessage *copy;
2068 uint64_t mask;
2069 unsigned int i;
2070 unsigned int delta;
2066 2071
2067 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_UNICAST_ACK); 2072 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_UNICAST_ACK);
2068 msg.header.size = htons (sizeof (msg)); 2073 msg.header.size = htons (sizeof (msg));
2069 msg.tid = htonl (t->id.tid); 2074 msg.tid = htonl (t->id.tid);
2070 GNUNET_PEER_resolve (t->id.oid, &msg.oid); 2075 GNUNET_PEER_resolve (t->id.oid, &msg.oid);
2071 msg.mid = GNUNET_htonll (t->bck_rel->mid_recv - 1); 2076 msg.mid = GNUNET_htonll (t->bck_rel->mid_recv - 1);
2072 msg.futures = 0; // FIXME set bits of other newer messages received 2077 msg.futures = 0;
2078 rel = t->bck_rel;
2079 for (i = 0, copy = rel->head_recv;
2080 i < 64 && NULL != copy;
2081 i++, copy = copy->next)
2082 {
2083 delta = copy->mid - t->bck_rel->mid_recv;
2084 mask = 0x1 << delta;
2085 msg.futures |= mask;
2086 }
2087 msg.futures = GNUNET_htonll (msg.futures);
2073 2088
2074 send_prebuilt_message (&msg.header, t->prev_hop, t); 2089 send_prebuilt_message (&msg.header, t->prev_hop, t);
2075} 2090}
@@ -2304,6 +2319,130 @@ tunnel_send_client_ucast (struct MeshTunnel *t,
2304 2319
2305 2320
2306/** 2321/**
2322 * Send up to 64 buffered messages to the client for in order delivery.
2323 *
2324 * @param t Tunnel on which to empty the message buffer.
2325 */
2326static void
2327tunnel_send_client_buffered_ucast (struct MeshTunnel *t)
2328{
2329 struct MeshTunnelReliability *rel;
2330 struct MeshReliableMessage *copy;
2331 struct MeshReliableMessage *next;
2332
2333 rel = t->bck_rel;
2334 for (copy = rel->head_recv; NULL != copy; copy = next)
2335 {
2336 next = copy->next;
2337 if (copy->mid == rel->mid_recv)
2338 {
2339 struct GNUNET_MESH_Data *msg = (struct GNUNET_MESH_Data *) &copy[1];
2340
2341 tunnel_send_client_ucast (t, msg);
2342 rel->mid_recv++;
2343 GNUNET_CONTAINER_DLL_remove (rel->head_recv, rel->tail_recv, copy);
2344 GNUNET_free (copy);
2345 }
2346 else
2347 {
2348 return;
2349 }
2350 }
2351}
2352
2353
2354/**
2355 * We have received a message out of order, buffer it until we receive
2356 * the missing one and we can feed the rest to the client.
2357 */
2358static void
2359tunnel_add_buffer_ucast (struct MeshTunnel *t,
2360 const struct GNUNET_MESH_Data *msg)
2361{
2362 struct MeshTunnelReliability *rel;
2363 struct MeshReliableMessage *copy;
2364 struct MeshReliableMessage *prev;
2365 uint64_t mid;
2366 uint16_t size;
2367
2368 rel = t->bck_rel;
2369 size = ntohs (msg->header.size);
2370 mid = GNUNET_ntohll (msg->mid);
2371
2372 copy = GNUNET_malloc (sizeof (*copy) + size);
2373 memcpy (&copy[1], msg, size);
2374
2375 // FIXME do something better than O(n), although n < 64...
2376 for (prev = rel->head_recv; NULL != prev; prev = prev->next)
2377 {
2378 if (mid < prev->mid)
2379 GNUNET_CONTAINER_DLL_insert_before (rel->head_recv, rel->tail_recv,
2380 prev, copy);
2381 return;
2382 }
2383 GNUNET_CONTAINER_DLL_insert_tail (rel->head_recv, rel->tail_recv, copy);
2384}
2385
2386
2387/**
2388 * Mark future messages as ACK'd.
2389 *
2390 * @param t Tunnel whose sent buffer to clean.
2391 * @param msg DataACK message with a bitfield of future ACK'd messages.
2392 */
2393static void
2394tunnel_free_buffer_ucast (struct MeshTunnel *t,
2395 const struct GNUNET_MESH_DataACK *msg)
2396{
2397 struct MeshTunnelReliability *rel;
2398 struct MeshReliableMessage *copy;
2399 struct MeshReliableMessage *next;
2400 uint64_t bitfield;
2401 uint64_t mask;
2402 uint64_t mid;
2403 uint64_t target;
2404 unsigned int i;
2405
2406 bitfield = GNUNET_ntohll (msg->futures);
2407 mid = GNUNET_ntohll (msg->mid);
2408 rel = t->fwd_rel;
2409 for (i = 0, copy = rel->head_recv;
2410 i < 64 && NULL != copy && 0 != bitfield;
2411 i++, copy = next)
2412 {
2413 mask = 0x1 << i;
2414 if (0 == (bitfield & mask))
2415 continue;
2416
2417 /* Bit was set, clear the bit from the bitfield */
2418 bitfield &= ~mask;
2419
2420 /* The i-th bit was set. Do we have that copy? */
2421 /* Skip copies with mid < target */
2422 target = mid + i + 1;
2423 while (NULL != copy && copy->mid < target)
2424 copy = copy->next;
2425
2426 /* Did we run out of copies? (previously freed, it's ok) */
2427 if (NULL == copy)
2428 return;
2429
2430 /* Did we overshoot the target? (previously freed, it's ok) */
2431 if (copy->mid > target)
2432 {
2433 next = copy;
2434 continue;
2435 }
2436
2437 /* Now copy->mid == target, free it */
2438 copy = copy->next;
2439 GNUNET_CONTAINER_DLL_remove (rel->head_sent, rel->tail_sent, copy);
2440 GNUNET_free (copy);
2441 }
2442}
2443
2444
2445/**
2307 * Modify the to_origin message TID from global to local and send to client. 2446 * Modify the to_origin message TID from global to local and send to client.
2308 * 2447 *
2309 * @param t Tunnel on which to send the message. 2448 * @param t Tunnel on which to send the message.
@@ -3785,22 +3924,31 @@ handle_mesh_unicast (void *cls, const struct GNUNET_PeerIdentity *peer,
3785 t->prev_fc.last_pid_recv = pid; 3924 t->prev_fc.last_pid_recv = pid;
3786 3925
3787 if (GNUNET_NO == t->reliable || 3926 if (GNUNET_NO == t->reliable ||
3788 (mid >= t->bck_rel->mid_recv && mid < t->bck_rel->mid_recv + 64)) 3927 (mid >= t->bck_rel->mid_recv && mid <= t->bck_rel->mid_recv + 64))
3789 { 3928 {
3790 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 3929 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3791 "!!! RECV %llu\n", GNUNET_ntohll(msg->mid)); 3930 "!!! RECV %llu\n", GNUNET_ntohll(msg->mid));
3792 if (GNUNET_YES == t->reliable) 3931 if (GNUNET_YES == t->reliable)
3793 { 3932 {
3933 /* Is this the exact next expected messasge? */
3794 if (mid == t->bck_rel->mid_recv) 3934 if (mid == t->bck_rel->mid_recv)
3935 {
3795 t->bck_rel->mid_recv++; 3936 t->bck_rel->mid_recv++;
3937 tunnel_send_client_ucast (t, msg);
3938 tunnel_send_client_buffered_ucast (t);
3939 }
3940 else
3941 {
3942 tunnel_add_buffer_ucast (t, msg);
3943 }
3796 } 3944 }
3797 tunnel_send_client_ucast (t, msg);
3798 } 3945 }
3799 else 3946 else
3800 { 3947 {
3801 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 3948 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3802 " MID %llu not expected (%llu), dropping!\n", 3949 " MID %llu not expected (%llu - %llu), dropping!\n",
3803 GNUNET_ntohll (msg->mid), t->bck_rel->mid_recv); 3950 GNUNET_ntohll (msg->mid),
3951 t->bck_rel->mid_recv, t->bck_rel->mid_recv + 64LL);
3804 } 3952 }
3805 } 3953 }
3806 else 3954 else
@@ -4032,6 +4180,7 @@ handle_mesh_data_ack (void *cls, const struct GNUNET_PeerIdentity *peer,
4032 if (copy->mid > ack) 4180 if (copy->mid > ack)
4033 { 4181 {
4034 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "!!! head %llu, out!\n", copy->mid); 4182 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "!!! head %llu, out!\n", copy->mid);
4183 tunnel_free_buffer_ucast (t, msg);
4035 break; 4184 break;
4036 } 4185 }
4037 work = GNUNET_YES; 4186 work = GNUNET_YES;