aboutsummaryrefslogtreecommitdiff
path: root/src/transport/gnunet-service-tng.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2019-04-20 18:04:28 +0200
committerChristian Grothoff <christian@grothoff.org>2019-04-20 18:04:37 +0200
commit941ec5c4fa6c6d4279b0d7546a49bae766fc6c65 (patch)
treec968be256019371c3d72d206e16c70b040321cfa /src/transport/gnunet-service-tng.c
parent6131cd0e220764ae6b9c016a3729d130cc53806d (diff)
downloadgnunet-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.c139
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 */
4637static void
4638check_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 */
4673static void
4674activate_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)
4664static int 4717static int
4665learn_dv_path (const struct GNUNET_PeerIdentity *path, 4718learn_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