diff options
author | Christian Grothoff <christian@grothoff.org> | 2019-04-20 18:04:28 +0200 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2019-04-20 18:04:37 +0200 |
commit | 941ec5c4fa6c6d4279b0d7546a49bae766fc6c65 (patch) | |
tree | c968be256019371c3d72d206e16c70b040321cfa /src/transport/gnunet-service-tng.c | |
parent | 6131cd0e220764ae6b9c016a3729d130cc53806d (diff) | |
download | gnunet-941ec5c4fa6c6d4279b0d7546a49bae766fc6c65.tar.gz gnunet-941ec5c4fa6c6d4279b0d7546a49bae766fc6c65.zip |
implement DV notifications towards core
Diffstat (limited to 'src/transport/gnunet-service-tng.c')
-rw-r--r-- | src/transport/gnunet-service-tng.c | 139 |
1 files changed, 103 insertions, 36 deletions
diff --git a/src/transport/gnunet-service-tng.c b/src/transport/gnunet-service-tng.c index ace248a23..3bef2b4e7 100644 --- a/src/transport/gnunet-service-tng.c +++ b/src/transport/gnunet-service-tng.c | |||
@@ -33,27 +33,6 @@ | |||
33 | * transport-to-transport traffic) | 33 | * transport-to-transport traffic) |
34 | * | 34 | * |
35 | * Implement next: | 35 | * Implement next: |
36 | * - route_message() implementation, including using DV data structures | ||
37 | * (but not when routing certain message types, like DV learn, | ||
38 | * looks like now like we need two flags (DV/no-DV, confirmed-only, | ||
39 | * unconfirmed OK) | ||
40 | * + NOTE: do NOT use PendingMessage for route_message(), as that is | ||
41 | * for fragmentation/reliability and ultimately core flow control! | ||
42 | * => route_message() should pick the queue | ||
43 | * => in case of DV routing, route_message should BOX the message, too. | ||
44 | * - We currently do NEVER tell CORE also about DV-connections (core_visible | ||
45 | * of `struct DistanceVector` is simply never set!) | ||
46 | * + When? Easy if we initiated the DV and got the challenge; do that NOW | ||
47 | * BUT what we passively learned DV (unconfirmed freshness) | ||
48 | * => Do we trigger Challenge->Response there as well, or 'wait' for | ||
49 | * our own DV initiations to discover? | ||
50 | * => What about DV routes that expire? Do we also only count on | ||
51 | * our own DV initiations for maintenance here, or do we | ||
52 | * try to specifically re-confirm the existence of a particular path? | ||
53 | * => OPITMIZATION-FIXME! | ||
54 | * + Where do we track what we told core? Careful: need to check | ||
55 | * the "core_visible' flag in both neighbours and DV before | ||
56 | * sending out notifications to CORE! | ||
57 | * - retransmission logic | 36 | * - retransmission logic |
58 | * - track RTT, distance, loss, etc. => requires extra data structures! | 37 | * - track RTT, distance, loss, etc. => requires extra data structures! |
59 | * | 38 | * |
@@ -69,6 +48,11 @@ | |||
69 | * fragments as just pointers into the original message and only | 48 | * fragments as just pointers into the original message and only |
70 | * fully build fragments just before transmission (optimization, should | 49 | * fully build fragments just before transmission (optimization, should |
71 | * reduce CPU and memory use) | 50 | * reduce CPU and memory use) |
51 | * - When we passively learned DV (with unconfirmed freshness), we | ||
52 | * right now add the path to our list but with a zero path_valid_until | ||
53 | * time and only use it for unconfirmed routes. However, we could consider | ||
54 | * triggering an explicit validation mechansim ourselves, specifically routing | ||
55 | * a challenge-response message over the path (OPTIMIZATION-FIXME). | ||
72 | * | 56 | * |
73 | * FIXME (without marks in the code!): | 57 | * FIXME (without marks in the code!): |
74 | * - proper use/initialization of timestamps in messages exchanged | 58 | * - proper use/initialization of timestamps in messages exchanged |
@@ -1043,14 +1027,13 @@ struct DistanceVectorHop | |||
1043 | struct GNUNET_TIME_Absolute timeout; | 1027 | struct GNUNET_TIME_Absolute timeout; |
1044 | 1028 | ||
1045 | /** | 1029 | /** |
1046 | * After what time do we know for sure that the path must have existed? | 1030 | * For how long is the validation of this path considered |
1031 | * valid? | ||
1047 | * Set to ZERO if the path is learned by snooping on DV learn messages | 1032 | * Set to ZERO if the path is learned by snooping on DV learn messages |
1048 | * initiated by other peers, and to the time at which we generated the | 1033 | * initiated by other peers, and to the time at which we generated the |
1049 | * challenge for DV learn operations this peer initiated. | 1034 | * challenge for DV learn operations this peer initiated. |
1050 | * | ||
1051 | * FIXME: freshness is currently never set! | ||
1052 | */ | 1035 | */ |
1053 | struct GNUNET_TIME_Absolute freshness; | 1036 | struct GNUNET_TIME_Absolute path_valid_until; |
1054 | 1037 | ||
1055 | /** | 1038 | /** |
1056 | * Number of hops in total to the `target` (excluding @e next_hop and `target` | 1039 | * Number of hops in total to the `target` (excluding @e next_hop and `target` |
@@ -1089,6 +1072,12 @@ struct DistanceVector | |||
1089 | struct GNUNET_SCHEDULER_Task *timeout_task; | 1072 | struct GNUNET_SCHEDULER_Task *timeout_task; |
1090 | 1073 | ||
1091 | /** | 1074 | /** |
1075 | * Task scheduled to possibly notfiy core that this queue is no longer | ||
1076 | * counting as confirmed. Runs the #core_queue_visibility_check(). | ||
1077 | */ | ||
1078 | struct GNUNET_SCHEDULER_Task *visibility_task; | ||
1079 | |||
1080 | /** | ||
1092 | * Is one of the DV paths in this struct 'confirmed' and thus | 1081 | * Is one of the DV paths in this struct 'confirmed' and thus |
1093 | * the cause for CORE to see this peer as connected? (Note that | 1082 | * the cause for CORE to see this peer as connected? (Note that |
1094 | * the same may apply to a `struct Neighbour` at the same time.) | 1083 | * the same may apply to a `struct Neighbour` at the same time.) |
@@ -2180,6 +2169,8 @@ free_dv_route (struct DistanceVector *dv) | |||
2180 | GNUNET_assert ( | 2169 | GNUNET_assert ( |
2181 | GNUNET_YES == | 2170 | GNUNET_YES == |
2182 | GNUNET_CONTAINER_multipeermap_remove (dv_routes, &dv->target, dv)); | 2171 | GNUNET_CONTAINER_multipeermap_remove (dv_routes, &dv->target, dv)); |
2172 | if (NULL != dv->visibility_task) | ||
2173 | GNUNET_SCHEDULER_cancel (dv->visibility_task); | ||
2183 | if (NULL != dv->timeout_task) | 2174 | if (NULL != dv->timeout_task) |
2184 | GNUNET_SCHEDULER_cancel (dv->timeout_task); | 2175 | GNUNET_SCHEDULER_cancel (dv->timeout_task); |
2185 | GNUNET_free (dv); | 2176 | GNUNET_free (dv); |
@@ -3427,8 +3418,8 @@ route_via_dv (const struct DistanceVector *dv, | |||
3427 | pos = pos->next_dv) | 3418 | pos = pos->next_dv) |
3428 | { | 3419 | { |
3429 | if ((0 == (options & RMO_UNCONFIRMED_ALLOWED)) && | 3420 | if ((0 == (options & RMO_UNCONFIRMED_ALLOWED)) && |
3430 | (GNUNET_TIME_absolute_get_duration (pos->freshness).rel_value_us > | 3421 | (GNUNET_TIME_absolute_get_remaining (pos->path_valid_until) |
3431 | ADDRESS_VALIDATION_LIFETIME.rel_value_us)) | 3422 | .rel_value_us == 0)) |
3432 | continue; /* pos unconfirmed and confirmed required */ | 3423 | continue; /* pos unconfirmed and confirmed required */ |
3433 | num_dv += MAX_DV_HOPS_ALLOWED - pos->distance; | 3424 | num_dv += MAX_DV_HOPS_ALLOWED - pos->distance; |
3434 | } | 3425 | } |
@@ -3448,8 +3439,8 @@ route_via_dv (const struct DistanceVector *dv, | |||
3448 | uint32_t delta = MAX_DV_HOPS_ALLOWED - pos->distance; | 3439 | uint32_t delta = MAX_DV_HOPS_ALLOWED - pos->distance; |
3449 | 3440 | ||
3450 | if ((0 == (options & RMO_UNCONFIRMED_ALLOWED)) && | 3441 | if ((0 == (options & RMO_UNCONFIRMED_ALLOWED)) && |
3451 | (GNUNET_TIME_absolute_get_duration (pos->freshness).rel_value_us > | 3442 | (GNUNET_TIME_absolute_get_remaining (pos->path_valid_until) |
3452 | ADDRESS_VALIDATION_LIFETIME.rel_value_us)) | 3443 | .rel_value_us == 0)) |
3453 | continue; /* pos unconfirmed and confirmed required */ | 3444 | continue; /* pos unconfirmed and confirmed required */ |
3454 | if ((num_dv <= choice1) && (num_dv + delta > choice1)) | 3445 | if ((num_dv <= choice1) && (num_dv + delta > choice1)) |
3455 | h1 = pos; | 3446 | h1 = pos; |
@@ -4637,6 +4628,66 @@ path_cleanup_cb (void *cls) | |||
4637 | GNUNET_SCHEDULER_add_at (pos->timeout, &path_cleanup_cb, dv); | 4628 | GNUNET_SCHEDULER_add_at (pos->timeout, &path_cleanup_cb, dv); |
4638 | } | 4629 | } |
4639 | 4630 | ||
4631 | /** | ||
4632 | * Task run to check whether the hops of the @a cls still | ||
4633 | * are validated, or if we need to core about disconnection. | ||
4634 | * | ||
4635 | * @param cls a `struct DistanceVector` (with core_visible set!) | ||
4636 | */ | ||
4637 | static void | ||
4638 | check_dv_path_down (void *cls) | ||
4639 | { | ||
4640 | struct DistanceVector *dv = cls; | ||
4641 | struct Neighbour *n; | ||
4642 | |||
4643 | dv->visibility_task = NULL; | ||
4644 | GNUNET_assert (GNUNET_YES == dv->core_visible); | ||
4645 | for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos; | ||
4646 | pos = pos->next_dv) | ||
4647 | { | ||
4648 | if (0 < | ||
4649 | GNUNET_TIME_absolute_get_remaining (pos->path_valid_until).rel_value_us) | ||
4650 | { | ||
4651 | dv->visibility_task = GNUNET_SCHEDULER_add_at (pos->path_valid_until, | ||
4652 | &check_dv_path_down, | ||
4653 | dv); | ||
4654 | return; | ||
4655 | } | ||
4656 | } | ||
4657 | /* all paths invalid, make dv core-invisible */ | ||
4658 | dv->core_visible = GNUNET_NO; | ||
4659 | n = GNUNET_CONTAINER_multipeermap_get (neighbours, &dv->target); | ||
4660 | if ((NULL != n) && (GNUNET_YES == n->core_visible)) | ||
4661 | return; /* no need to tell core, connection still up! */ | ||
4662 | cores_send_disconnect_info (&dv->target); | ||
4663 | } | ||
4664 | |||
4665 | |||
4666 | /** | ||
4667 | * The @a hop is a validated path to the respective target | ||
4668 | * peer and we should tell core about it -- and schedule | ||
4669 | * a job to revoke the state. | ||
4670 | * | ||
4671 | * @param hop a path to some peer that is the reason for activation | ||
4672 | */ | ||
4673 | static void | ||
4674 | activate_core_visible_dv_path (struct DistanceVectorHop *hop) | ||
4675 | { | ||
4676 | struct DistanceVector *dv = hop->dv; | ||
4677 | struct Neighbour *n; | ||
4678 | |||
4679 | GNUNET_assert (GNUNET_NO == dv->core_visible); | ||
4680 | GNUNET_assert (NULL == dv->visibility_task); | ||
4681 | |||
4682 | dv->core_visible = GNUNET_YES; | ||
4683 | dv->visibility_task = | ||
4684 | GNUNET_SCHEDULER_add_at (hop->path_valid_until, &check_dv_path_down, dv); | ||
4685 | n = GNUNET_CONTAINER_multipeermap_get (neighbours, &dv->target); | ||
4686 | if ((NULL != n) && (GNUNET_YES == n->core_visible)) | ||
4687 | return; /* no need to tell core, connection already up! */ | ||
4688 | cores_send_connect_info (&dv->target, GNUNET_BANDWIDTH_ZERO); | ||
4689 | } | ||
4690 | |||
4640 | 4691 | ||
4641 | /** | 4692 | /** |
4642 | * We have learned a @a path through the network to some other peer, add it to | 4693 | * We have learned a @a path through the network to some other peer, add it to |
@@ -4655,6 +4706,8 @@ path_cleanup_cb (void *cls) | |||
4655 | * @param path_len number of entries on the @a path, at least three! | 4706 | * @param path_len number of entries on the @a path, at least three! |
4656 | * @param network_latency how long does the message take from us to | 4707 | * @param network_latency how long does the message take from us to |
4657 | * `path[path_len-1]`? set to "forever" if unknown | 4708 | * `path[path_len-1]`? set to "forever" if unknown |
4709 | * @param path_valid_until how long is this path considered validated? Maybe be | ||
4710 | * zero. | ||
4658 | * @return #GNUNET_YES on success, | 4711 | * @return #GNUNET_YES on success, |
4659 | * #GNUNET_NO if we have better path(s) to the target | 4712 | * #GNUNET_NO if we have better path(s) to the target |
4660 | * #GNUNET_SYSERR if the path is useless and/or invalid | 4713 | * #GNUNET_SYSERR if the path is useless and/or invalid |
@@ -4664,7 +4717,8 @@ path_cleanup_cb (void *cls) | |||
4664 | static int | 4717 | static int |
4665 | learn_dv_path (const struct GNUNET_PeerIdentity *path, | 4718 | learn_dv_path (const struct GNUNET_PeerIdentity *path, |
4666 | unsigned int path_len, | 4719 | unsigned int path_len, |
4667 | struct GNUNET_TIME_Relative network_latency) | 4720 | struct GNUNET_TIME_Relative network_latency, |
4721 | struct GNUNET_TIME_Absolute path_valid_until) | ||
4668 | { | 4722 | { |
4669 | struct DistanceVectorHop *hop; | 4723 | struct DistanceVectorHop *hop; |
4670 | struct DistanceVector *dv; | 4724 | struct DistanceVector *dv; |
@@ -4742,8 +4796,14 @@ learn_dv_path (const struct GNUNET_PeerIdentity *path, | |||
4742 | last_timeout = GNUNET_TIME_absolute_get_remaining (pos->timeout); | 4796 | last_timeout = GNUNET_TIME_absolute_get_remaining (pos->timeout); |
4743 | pos->timeout = | 4797 | pos->timeout = |
4744 | GNUNET_TIME_relative_to_absolute (DV_PATH_VALIDITY_TIMEOUT); | 4798 | GNUNET_TIME_relative_to_absolute (DV_PATH_VALIDITY_TIMEOUT); |
4799 | pos->path_valid_until = | ||
4800 | GNUNET_TIME_absolute_max (pos->path_valid_until, path_valid_until); | ||
4745 | GNUNET_CONTAINER_MDLL_remove (dv, dv->dv_head, dv->dv_tail, pos); | 4801 | GNUNET_CONTAINER_MDLL_remove (dv, dv->dv_head, dv->dv_tail, pos); |
4746 | GNUNET_CONTAINER_MDLL_insert (dv, dv->dv_head, dv->dv_tail, pos); | 4802 | GNUNET_CONTAINER_MDLL_insert (dv, dv->dv_head, dv->dv_tail, pos); |
4803 | if ((GNUNET_NO == dv->core_visible) && | ||
4804 | (0 < GNUNET_TIME_absolute_get_remaining (path_valid_until) | ||
4805 | .rel_value_us)) | ||
4806 | activate_core_visible_dv_path (pos); | ||
4747 | if (last_timeout.rel_value_us < | 4807 | if (last_timeout.rel_value_us < |
4748 | GNUNET_TIME_relative_subtract (DV_PATH_VALIDITY_TIMEOUT, | 4808 | GNUNET_TIME_relative_subtract (DV_PATH_VALIDITY_TIMEOUT, |
4749 | DV_PATH_DISCOVERY_FREQUENCY) | 4809 | DV_PATH_DISCOVERY_FREQUENCY) |
@@ -4774,12 +4834,16 @@ learn_dv_path (const struct GNUNET_PeerIdentity *path, | |||
4774 | &path[2], | 4834 | &path[2], |
4775 | sizeof (struct GNUNET_PeerIdentity) * (path_len - 2)); | 4835 | sizeof (struct GNUNET_PeerIdentity) * (path_len - 2)); |
4776 | hop->timeout = GNUNET_TIME_relative_to_absolute (DV_PATH_VALIDITY_TIMEOUT); | 4836 | hop->timeout = GNUNET_TIME_relative_to_absolute (DV_PATH_VALIDITY_TIMEOUT); |
4837 | hop->path_valid_until = path_valid_until; | ||
4777 | hop->distance = path_len - 2; | 4838 | hop->distance = path_len - 2; |
4778 | GNUNET_CONTAINER_MDLL_insert (dv, dv->dv_head, dv->dv_tail, hop); | 4839 | GNUNET_CONTAINER_MDLL_insert (dv, dv->dv_head, dv->dv_tail, hop); |
4779 | GNUNET_CONTAINER_MDLL_insert (neighbour, | 4840 | GNUNET_CONTAINER_MDLL_insert (neighbour, |
4780 | next_hop->dv_head, | 4841 | next_hop->dv_head, |
4781 | next_hop->dv_tail, | 4842 | next_hop->dv_tail, |
4782 | hop); | 4843 | hop); |
4844 | if ((GNUNET_NO == dv->core_visible) && | ||
4845 | (0 < GNUNET_TIME_absolute_get_remaining (path_valid_until).rel_value_us)) | ||
4846 | activate_core_visible_dv_path (hop); | ||
4783 | return GNUNET_YES; | 4847 | return GNUNET_YES; |
4784 | } | 4848 | } |
4785 | 4849 | ||
@@ -5013,11 +5077,11 @@ handle_dv_learn (void *cls, const struct TransportDVLearn *dvl) | |||
5013 | /* assumption: linear latency increase per hop */ | 5077 | /* assumption: linear latency increase per hop */ |
5014 | ilat = GNUNET_TIME_relative_multiply (network_latency, i); | 5078 | ilat = GNUNET_TIME_relative_multiply (network_latency, i); |
5015 | path[i] = hops[i - 1].hop; | 5079 | path[i] = hops[i - 1].hop; |
5016 | // FIXME: mark ALL of these as *confirmed* (with what timeout?) | 5080 | learn_dv_path (path, |
5017 | // -- and schedule a job for the confirmation to time out! -- | 5081 | i, |
5018 | // and possibly do #cores_send_connect_info() if | 5082 | ilat, |
5019 | // the respective neighbour is NOT confirmed yet! | 5083 | GNUNET_TIME_relative_to_absolute ( |
5020 | learn_dv_path (path, i, ilat); | 5084 | ADDRESS_VALIDATION_LIFETIME)); |
5021 | } | 5085 | } |
5022 | /* as we initiated, do not forward again (would be circular!) */ | 5086 | /* as we initiated, do not forward again (would be circular!) */ |
5023 | do_fwd = GNUNET_NO; | 5087 | do_fwd = GNUNET_NO; |
@@ -5045,7 +5109,10 @@ handle_dv_learn (void *cls, const struct TransportDVLearn *dvl) | |||
5045 | path[i + 2] = hops[nhops - i - 2].hop; | 5109 | path[i + 2] = hops[nhops - i - 2].hop; |
5046 | } | 5110 | } |
5047 | 5111 | ||
5048 | iret = learn_dv_path (path, i + 2, GNUNET_TIME_UNIT_FOREVER_REL); | 5112 | iret = learn_dv_path (path, |
5113 | i + 2, | ||
5114 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
5115 | GNUNET_TIME_UNIT_ZERO_ABS); | ||
5049 | if (GNUNET_SYSERR == iret) | 5116 | if (GNUNET_SYSERR == iret) |
5050 | { | 5117 | { |
5051 | /* path invalid or too long to be interesting for US, thus should also | 5118 | /* path invalid or too long to be interesting for US, thus should also |