diff options
author | Bart Polot <bart@net.in.tum.de> | 2013-07-13 10:15:16 +0000 |
---|---|---|
committer | Bart Polot <bart@net.in.tum.de> | 2013-07-13 10:15:16 +0000 |
commit | 1a8ad09983f69db13cc992311cbf1320caca4d67 (patch) | |
tree | b5387ab4411f1be2f13b63f05fbfbbf959df8568 /src | |
parent | c82adc2479b9144ab5aec6a1631d669385219856 (diff) | |
download | gnunet-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.c | 159 |
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 | |||
2063 | tunnel_send_fwd_data_ack (struct MeshTunnel *t) | 2063 | tunnel_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 | */ | ||
2326 | static void | ||
2327 | tunnel_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 *) ©[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 | */ | ||
2358 | static void | ||
2359 | tunnel_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 (©[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 | */ | ||
2393 | static void | ||
2394 | tunnel_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; |