From fc99f54070e04c043c14f2244f85833ecf6b00c4 Mon Sep 17 00:00:00 2001 From: t3sserakt Date: Fri, 21 Jan 2022 15:31:44 +0100 Subject: - fixed bug with broadcast test. - added configurable port for router in netjail_start.sh. - added key for configuring broadcast in topo.sh. - port for communicators can variable. - added variable additional_connects in GNUNET_TESTING_NetjailTopology. - additional connects can be configured in topology file. - added distance vector test with circle topology. - Reassambly for fragmentation is now stored at VirtualLink, not at Neighbour. - DV forwarding distingush between control flow and payload. - handling fragment box switch to be based on VirtualLink. - reliability box will not be handled like a fragment. - propagating next retransmission attempt variable of fragment to the root message. - check for fragmentation when adding reliability box. - several smaller bug fixes. --- contrib/netjail/netjail_start.sh | 9 +- contrib/netjail/topo.sh | 4 + po/POTFILES.in | 1 - src/include/gnunet_testing_netjail_lib.h | 5 + src/testing/testing.c | 24 +- .../testing_api_cmd_netjail_start_testsystem.c | 6 +- src/transport/Makefile.am | 4 +- src/transport/gnunet-service-tng.c | 645 ++++++++++++--------- .../test_transport_distance_vector_topo.conf | 8 + src/transport/test_transport_hmac_calculation.c | 250 -------- .../test_transport_plugin_cmd_simple_send_dv.c | 109 +++- .../test_transport_simple_send_dv_circle.sh | 12 + src/transport/transport-testing-cmds.h | 5 +- src/transport/transport_api_cmd_connecting_peers.c | 39 +- src/transport/transport_api_cmd_start_peer.c | 4 +- 15 files changed, 559 insertions(+), 566 deletions(-) create mode 100644 src/transport/test_transport_distance_vector_topo.conf delete mode 100644 src/transport/test_transport_hmac_calculation.c create mode 100755 src/transport/test_transport_simple_send_dv_circle.sh diff --git a/contrib/netjail/netjail_start.sh b/contrib/netjail/netjail_start.sh index 997ad0a95..f7c417c27 100755 --- a/contrib/netjail/netjail_start.sh +++ b/contrib/netjail/netjail_start.sh @@ -11,6 +11,8 @@ filename=$1 PREFIX=$2 readfile=$3 +BROADCAST=0 + if [ $readfile -eq 0 ] then read_topology_string "$filename" @@ -25,6 +27,11 @@ LOCAL_GROUP="192.168.15" GLOBAL_GROUP="92.68.150" KNOWN_GROUP="92.68.151" +if [ $BROADCAST -eq 0 ]; then + PORT="60002" +else + PORT="2086" +fi echo "Start [local: $LOCAL_GROUP.0/24, global: $GLOBAL_GROUP.0/16]" @@ -75,7 +82,7 @@ for N in $(seq $GLOBAL_N); do fi if [ "1" == "${R_UDP[$N]}" ] then - ip netns exec ${ROUTERS[$N]} iptables -t nat -A PREROUTING -p udp -d $GLOBAL_GROUP.$N --dport 60002 -j DNAT --to $LOCAL_GROUP.1 + ip netns exec ${ROUTERS[$N]} iptables -t nat -A PREROUTING -p udp -d $GLOBAL_GROUP.$N --dport $PORT -j DNAT --to $LOCAL_GROUP.1 ip netns exec ${ROUTERS[$N]} iptables -A FORWARD -d $LOCAL_GROUP.1 -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT fi done diff --git a/contrib/netjail/topo.sh b/contrib/netjail/topo.sh index 9af017ff0..d7586d425 100755 --- a/contrib/netjail/topo.sh +++ b/contrib/netjail/topo.sh @@ -76,6 +76,10 @@ parse_line(){ then PLUGIN=$(cut -d : -f 2 <<< $line) echo $PLUGIN + elif [ "$key" = "B" ] + then + BROADCAST=$(cut -d : -f 2 <<< $line) + echo $BROADCAST elif [ "$key" = "K" ] then echo know node diff --git a/po/POTFILES.in b/po/POTFILES.in index 94b64e5b3..ffa06a484 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -314,7 +314,6 @@ src/reclaim/plugin_rest_reclaim.c src/reclaim/reclaim_api.c src/reclaim/reclaim_attribute.c src/reclaim/reclaim_credential.c -src/reclaim/test.c src/regex/gnunet-daemon-regexprofiler.c src/regex/gnunet-regex-profiler.c src/regex/gnunet-regex-simulation-profiler.c diff --git a/src/include/gnunet_testing_netjail_lib.h b/src/include/gnunet_testing_netjail_lib.h index 69d6e7a7d..4b5d7cfa1 100644 --- a/src/include/gnunet_testing_netjail_lib.h +++ b/src/include/gnunet_testing_netjail_lib.h @@ -232,6 +232,11 @@ struct GNUNET_TESTING_NetjailTopology * Hash map containing the global known nodes which are not natted. */ struct GNUNET_CONTAINER_MultiShortmap *map_globals; + + /** + * Additional connects we do expect, beside the connects which are configured in the topology. + */ + unsigned int additional_connects; }; /** diff --git a/src/testing/testing.c b/src/testing/testing.c index fd0701d7d..6480d32f9 100644 --- a/src/testing/testing.c +++ b/src/testing/testing.c @@ -38,11 +38,11 @@ #define LOG(kind, ...) GNUNET_log_from (kind, "testing-api", __VA_ARGS__) -#define CONNECT_ADDRESS_TEMPLATE "%s-192.168.15.%u:60002" +#define CONNECT_ADDRESS_TEMPLATE "%s-192.168.15.%u" -#define ROUTER_CONNECT_ADDRESS_TEMPLATE "%s-92.68.150.%u:60002" +#define ROUTER_CONNECT_ADDRESS_TEMPLATE "%s-92.68.150.%u" -#define KNOWN_CONNECT_ADDRESS_TEMPLATE "%s-92.68.151.%u:60002" +#define KNOWN_CONNECT_ADDRESS_TEMPLATE "%s-92.68.151.%u" #define PREFIX_TCP "tcp" @@ -2298,6 +2298,7 @@ GNUNET_TESTING_get_address (struct GNUNET_TESTING_NodeConnection *connection, struct GNUNET_TESTING_NetjailNode *node; char *addr; char *template; + unsigned int node_n; LOG (GNUNET_ERROR_TYPE_DEBUG, "node_n: %u\n", @@ -2307,14 +2308,17 @@ GNUNET_TESTING_get_address (struct GNUNET_TESTING_NodeConnection *connection, if (connection->namespace_n == node->namespace_n) { template = CONNECT_ADDRESS_TEMPLATE; + node_n = connection->node_n; } else if (0 == connection->namespace_n) { template = KNOWN_CONNECT_ADDRESS_TEMPLATE; + node_n = connection->node_n; } else if (1 == connection->node_n) { template = ROUTER_CONNECT_ADDRESS_TEMPLATE; + node_n = connection->namespace_n; } else { @@ -2327,14 +2331,14 @@ GNUNET_TESTING_get_address (struct GNUNET_TESTING_NodeConnection *connection, GNUNET_asprintf (&addr, template, prefix, - connection->node_n); + node_n); } else if (0 == strcmp (PREFIX_UDP, prefix)) { GNUNET_asprintf (&addr, template, prefix, - connection->node_n); + node_n); } else { @@ -2439,6 +2443,16 @@ GNUNET_TESTING_get_topo_from_string (char *data) out); topo->nodes_x = out; } + else if (0 == strcmp (key, "AC")) + { + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Get first Value for AC.\n"); + out = get_first_value (token); + LOG (GNUNET_ERROR_TYPE_DEBUG, + "AC: %u\n", + out); + topo->additional_connects = out; + } else if (0 == strcmp (key, "T")) { LOG (GNUNET_ERROR_TYPE_DEBUG, diff --git a/src/testing/testing_api_cmd_netjail_start_testsystem.c b/src/testing/testing_api_cmd_netjail_start_testsystem.c index 9f39fbfda..0624a7f46 100644 --- a/src/testing/testing_api_cmd_netjail_start_testsystem.c +++ b/src/testing/testing_api_cmd_netjail_start_testsystem.c @@ -499,11 +499,11 @@ helper_mst (void *cls, const struct GNUNET_MessageHeader *message) static void exp_cb (void *cls) { - struct TestingSystemCount *tbc = cls; + struct NetJailState *ns = cls; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Called exp_cb.\n"); - GNUNET_SCHEDULER_cancel (tbc->ns->timeout_task); - GNUNET_TESTING_async_fail (&(tbc->ns->ac)); + GNUNET_SCHEDULER_cancel (ns->timeout_task); + GNUNET_TESTING_async_fail (&(ns->ac)); } diff --git a/src/transport/Makefile.am b/src/transport/Makefile.am index ed5a2ef54..6e8ceb638 100644 --- a/src/transport/Makefile.am +++ b/src/transport/Makefile.am @@ -779,7 +779,9 @@ check_SCRIPTS= \ test_transport_simple_send_string.sh \ test_transport_simple_send.sh \ test_transport_simple_send_broadcast.sh \ - test_transport_udp_backchannel.sh + test_transport_udp_backchannel.sh \ + test_transport_simple_send_dv_circle.sh + # test_transport_simple_send_dv_inverse.sh test_transport_start_with_config_SOURCES = \ test_transport_start_with_config.c diff --git a/src/transport/gnunet-service-tng.c b/src/transport/gnunet-service-tng.c index e41a1b000..56a854a70 100644 --- a/src/transport/gnunet-service-tng.c +++ b/src/transport/gnunet-service-tng.c @@ -741,6 +741,11 @@ struct TransportDVBoxMessage */ struct GNUNET_MessageHeader header; + /** + * Flag if the payload is a control message. In NBO. + */ + unsigned int without_fc; + /** * Number of total hops this messages travelled. In NBO. * @e origin sets this to zero, to be incremented at @@ -1197,6 +1202,65 @@ struct CoreSentContext }; +/** + * Information we keep for a message that we are reassembling. + */ +struct ReassemblyContext +{ + /** + * Original message ID for of the message that all the fragments + * belong to. + */ + struct MessageUUIDP msg_uuid; + + /** + * Which neighbour is this context for? + */ + struct VirtualLink *virtual_link; + + /** + * Entry in the reassembly heap (sorted by expiration). + */ + struct GNUNET_CONTAINER_HeapNode *hn; + + /** + * Bitfield with @e msg_size bits representing the positions + * where we have received fragments. When we receive a fragment, + * we check the bits in @e bitfield before incrementing @e msg_missing. + * + * Allocated after the reassembled message. + */ + uint8_t *bitfield; + + /** + * At what time will we give up reassembly of this message? + */ + struct GNUNET_TIME_Absolute reassembly_timeout; + + /** + * Time we received the last fragment. @e avg_ack_delay must be + * incremented by now - @e last_frag multiplied by @e num_acks. + */ + struct GNUNET_TIME_Absolute last_frag; + + /** + * How big is the message we are reassembling in total? + */ + uint16_t msg_size; + + /** + * How many bytes of the message are still missing? Defragmentation + * is complete when @e msg_missing == 0. + */ + uint16_t msg_missing; + + /* Followed by @e msg_size bytes of the (partially) defragmented original + * message */ + + /* Followed by @e bitfield data */ +}; + + /** * A virtual link is another reachable peer that is known to CORE. It * can be either a `struct Neighbour` with at least one confirmed @@ -1212,6 +1276,25 @@ struct VirtualLink */ struct GNUNET_PeerIdentity target; + /** + * Map with `struct ReassemblyContext` structs for fragments under + * reassembly. May be NULL if we currently have no fragments from + * this @e pid (lazy initialization). + */ + struct GNUNET_CONTAINER_MultiHashMap32 *reassembly_map; + + /** + * Heap with `struct ReassemblyContext` structs for fragments under + * reassembly. May be NULL if we currently have no fragments from + * this @e pid (lazy initialization). + */ + struct GNUNET_CONTAINER_Heap *reassembly_heap; + + /** + * Task to free old entries from the @e reassembly_heap and @e reassembly_map. + */ + struct GNUNET_SCHEDULER_Task *reassembly_timeout_task; + /** * Communicators blocked for receiving on @e target as we are waiting * on the @e core_recv_window to increase. @@ -1819,63 +1902,7 @@ struct Queue }; -/** - * Information we keep for a message that we are reassembling. - */ -struct ReassemblyContext -{ - /** - * Original message ID for of the message that all the fragments - * belong to. - */ - struct MessageUUIDP msg_uuid; - /** - * Which neighbour is this context for? - */ - struct Neighbour *neighbour; - - /** - * Entry in the reassembly heap (sorted by expiration). - */ - struct GNUNET_CONTAINER_HeapNode *hn; - - /** - * Bitfield with @e msg_size bits representing the positions - * where we have received fragments. When we receive a fragment, - * we check the bits in @e bitfield before incrementing @e msg_missing. - * - * Allocated after the reassembled message. - */ - uint8_t *bitfield; - - /** - * At what time will we give up reassembly of this message? - */ - struct GNUNET_TIME_Absolute reassembly_timeout; - - /** - * Time we received the last fragment. @e avg_ack_delay must be - * incremented by now - @e last_frag multiplied by @e num_acks. - */ - struct GNUNET_TIME_Absolute last_frag; - - /** - * How big is the message we are reassembling in total? - */ - uint16_t msg_size; - - /** - * How many bytes of the message are still missing? Defragmentation - * is complete when @e msg_missing == 0. - */ - uint16_t msg_missing; - - /* Followed by @e msg_size bytes of the (partially) defragmented original - * message */ - - /* Followed by @e bitfield data */ -}; /** @@ -1888,25 +1915,6 @@ struct Neighbour */ struct GNUNET_PeerIdentity pid; - /** - * Map with `struct ReassemblyContext` structs for fragments under - * reassembly. May be NULL if we currently have no fragments from - * this @e pid (lazy initialization). - */ - struct GNUNET_CONTAINER_MultiHashMap32 *reassembly_map; - - /** - * Heap with `struct ReassemblyContext` structs for fragments under - * reassembly. May be NULL if we currently have no fragments from - * this @e pid (lazy initialization). - */ - struct GNUNET_CONTAINER_Heap *reassembly_heap; - - /** - * Task to free old entries from the @e reassembly_heap and @e reassembly_map. - */ - struct GNUNET_SCHEDULER_Task *reassembly_timeout_task; - /** * Head of MDLL of DV hops that have this neighbour as next hop. Must be * purged if this neighbour goes down. @@ -2940,6 +2948,75 @@ free_pending_message (struct PendingMessage *pm) } +/** + * Free @a rc + * + * @param rc data structure to free + */ +static void +free_reassembly_context (struct ReassemblyContext *rc) +{ + struct VirtualLink *vl = rc->virtual_link; + + GNUNET_assert (rc == GNUNET_CONTAINER_heap_remove_node (rc->hn)); + GNUNET_assert (GNUNET_OK == + GNUNET_CONTAINER_multihashmap32_remove (vl->reassembly_map, + rc->msg_uuid.uuid, + rc)); + GNUNET_free (rc); +} + + +/** + * Task run to clean up reassembly context of a neighbour that have expired. + * + * @param cls a `struct Neighbour` + */ +static void +reassembly_cleanup_task (void *cls) +{ + struct VirtualLink *vl = cls; + struct ReassemblyContext *rc; + + vl->reassembly_timeout_task = NULL; + while (NULL != (rc = GNUNET_CONTAINER_heap_peek (vl->reassembly_heap))) + { + if (0 == GNUNET_TIME_absolute_get_remaining (rc->reassembly_timeout) + .rel_value_us) + { + free_reassembly_context (rc); + continue; + } + GNUNET_assert (NULL == vl->reassembly_timeout_task); + vl->reassembly_timeout_task = + GNUNET_SCHEDULER_add_at (rc->reassembly_timeout, + &reassembly_cleanup_task, + vl); + return; + } +} + + +/** + * function called to #free_reassembly_context(). + * + * @param cls NULL + * @param key unused + * @param value a `struct ReassemblyContext` to free + * @return #GNUNET_OK (continue iteration) + */ +static int +free_reassembly_cb (void *cls, uint32_t key, void *value) +{ + struct ReassemblyContext *rc = value; + + (void) cls; + (void) key; + free_reassembly_context (rc); + return GNUNET_OK; +} + + /** * Free virtual link. * @@ -2951,6 +3028,21 @@ free_virtual_link (struct VirtualLink *vl) struct PendingMessage *pm; struct CoreSentContext *csc; + if (NULL != vl->reassembly_map) + { + GNUNET_CONTAINER_multihashmap32_iterate (vl->reassembly_map, + &free_reassembly_cb, + NULL); + GNUNET_CONTAINER_multihashmap32_destroy (vl->reassembly_map); + vl->reassembly_map = NULL; + GNUNET_CONTAINER_heap_destroy (vl->reassembly_heap); + vl->reassembly_heap = NULL; + } + if (NULL != vl->reassembly_timeout_task) + { + GNUNET_SCHEDULER_cancel (vl->reassembly_timeout_task); + vl->reassembly_timeout_task = NULL; + } while (NULL != (pm = vl->pending_msg_head)) free_pending_message (pm); GNUNET_assert (GNUNET_YES == @@ -3267,75 +3359,6 @@ client_connect_cb (void *cls, } -/** - * Free @a rc - * - * @param rc data structure to free - */ -static void -free_reassembly_context (struct ReassemblyContext *rc) -{ - struct Neighbour *n = rc->neighbour; - - GNUNET_assert (rc == GNUNET_CONTAINER_heap_remove_node (rc->hn)); - GNUNET_assert (GNUNET_OK == - GNUNET_CONTAINER_multihashmap32_remove (n->reassembly_map, - rc->msg_uuid.uuid, - rc)); - GNUNET_free (rc); -} - - -/** - * Task run to clean up reassembly context of a neighbour that have expired. - * - * @param cls a `struct Neighbour` - */ -static void -reassembly_cleanup_task (void *cls) -{ - struct Neighbour *n = cls; - struct ReassemblyContext *rc; - - n->reassembly_timeout_task = NULL; - while (NULL != (rc = GNUNET_CONTAINER_heap_peek (n->reassembly_heap))) - { - if (0 == GNUNET_TIME_absolute_get_remaining (rc->reassembly_timeout) - .rel_value_us) - { - free_reassembly_context (rc); - continue; - } - GNUNET_assert (NULL == n->reassembly_timeout_task); - n->reassembly_timeout_task = - GNUNET_SCHEDULER_add_at (rc->reassembly_timeout, - &reassembly_cleanup_task, - n); - return; - } -} - - -/** - * function called to #free_reassembly_context(). - * - * @param cls NULL - * @param key unused - * @param value a `struct ReassemblyContext` to free - * @return #GNUNET_OK (continue iteration) - */ -static int -free_reassembly_cb (void *cls, uint32_t key, void *value) -{ - struct ReassemblyContext *rc = value; - - (void) cls; - (void) key; - free_reassembly_context (rc); - return GNUNET_OK; -} - - /** * Release memory used by @a neighbour. * @@ -3354,16 +3377,6 @@ free_neighbour (struct Neighbour *neighbour) neighbour)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Freeing neighbour\n"); - if (NULL != neighbour->reassembly_map) - { - GNUNET_CONTAINER_multihashmap32_iterate (neighbour->reassembly_map, - &free_reassembly_cb, - NULL); - GNUNET_CONTAINER_multihashmap32_destroy (neighbour->reassembly_map); - neighbour->reassembly_map = NULL; - GNUNET_CONTAINER_heap_destroy (neighbour->reassembly_heap); - neighbour->reassembly_heap = NULL; - } while (NULL != (dvh = neighbour->dv_head)) { struct DistanceVector *dv = dvh->dv; @@ -3372,11 +3385,6 @@ free_neighbour (struct Neighbour *neighbour) if (NULL == dv->dv_head) free_dv_route (dv); } - if (NULL != neighbour->reassembly_timeout_task) - { - GNUNET_SCHEDULER_cancel (neighbour->reassembly_timeout_task); - neighbour->reassembly_timeout_task = NULL; - } if (NULL != neighbour->get) { GNUNET_PEERSTORE_iterate_cancel (neighbour->get); @@ -4232,9 +4240,10 @@ update_ephemeral (struct DistanceVector *dv) GNUNET_CRYPTO_ecdhe_key_create (&dv->private_key); GNUNET_CRYPTO_ecdhe_key_get_public (&dv->private_key, &dv->ephemeral_key); ec.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL); - ec.purpose.size = htonl (sizeof(ec)); ec.target = dv->target; ec.ephemeral_key = dv->ephemeral_key; + ec.sender_monotonic_time = GNUNET_TIME_absolute_hton (dv->monotime); + ec.purpose.size = htonl (sizeof(ec)); GNUNET_CRYPTO_eddsa_sign (GST_my_private_key, &ec, &dv->sender_sig); @@ -4455,7 +4464,8 @@ dv_setup_key_state_from_km (const struct GNUNET_HashCode *km, km, sizeof(*km), iv, - sizeof(*iv))); + sizeof(*iv), + NULL)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Deriving backchannel key based on KM %s and IV %s\n", GNUNET_h2s (km), @@ -4616,6 +4626,7 @@ typedef void (*DVMessageHandler) (void *cls, * @param use function to call with the encapsulated message * @param use_cls closure for @a use * @param options whether path must be confirmed or not, to be passed to @a use + * @param shall this TransportDVBoxMessage be forwarded without flow control. * @return expected RTT for transmission, #GNUNET_TIME_UNIT_FOREVER_REL if sending failed */ static struct GNUNET_TIME_Relative @@ -4625,7 +4636,8 @@ encapsulate_for_dv (struct DistanceVector *dv, const struct GNUNET_MessageHeader *hdr, DVMessageHandler use, void *use_cls, - enum RouteMessageOptions options) + enum RouteMessageOptions options, + enum GNUNET_GenericReturnValue without_fc) { struct TransportDVBoxMessage box_hdr; struct TransportDVBoxPayloadP payload_hdr; @@ -4633,28 +4645,31 @@ encapsulate_for_dv (struct DistanceVector *dv, char enc[sizeof(struct TransportDVBoxPayloadP) + enc_body_size] GNUNET_ALIGN; struct TransportDVBoxPayloadP *enc_payload_hdr = (struct TransportDVBoxPayloadP *) enc; - struct DVKeyState key; + struct DVKeyState *key; struct GNUNET_TIME_Relative rtt; + key = GNUNET_new (struct DVKeyState); /* Encrypt payload */ box_hdr.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_DV_BOX); box_hdr.total_hops = htons (0); + box_hdr.without_fc = htons (without_fc); update_ephemeral (dv); box_hdr.ephemeral_key = dv->ephemeral_key; payload_hdr.sender_sig = dv->sender_sig; + GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE, &box_hdr.iv, sizeof(box_hdr.iv)); - dh_key_derive_eph_pid (&dv->private_key, &dv->target, &box_hdr.iv, &key); + dh_key_derive_eph_pid (&dv->private_key, &dv->target, &box_hdr.iv, key); payload_hdr.sender = GST_my_identity; payload_hdr.monotonic_time = GNUNET_TIME_absolute_hton (dv->monotime); - dv_encrypt (&key, &payload_hdr, enc_payload_hdr, sizeof(payload_hdr)); - dv_encrypt (&key, + dv_encrypt (key, &payload_hdr, enc_payload_hdr, sizeof(payload_hdr)); + dv_encrypt (key, hdr, &enc[sizeof(struct TransportDVBoxPayloadP)], enc_body_size); - dv_hmac (&key, &box_hdr.hmac, enc, sizeof(enc)); - dv_key_clean (&key); + dv_hmac (key, &box_hdr.hmac, enc, sizeof(enc)); + dv_key_clean (key); rtt = GNUNET_TIME_UNIT_FOREVER_REL; /* For each selected path, take the pre-computed header and body and add the path in the middle of the message; then send it. */ @@ -4681,7 +4696,7 @@ encapsulate_for_dv (struct DistanceVector *dv, char *path; path = GNUNET_strdup (GNUNET_i2s (&GST_my_identity)); - for (unsigned int j = 0; j <= num_hops; j++) + for (unsigned int j = 0; j < num_hops; j++) { char *tmp; @@ -4694,7 +4709,7 @@ encapsulate_for_dv (struct DistanceVector *dv, ntohs (hdr->type), GNUNET_i2s (&dv->target), i + 1, - num_dvhs + 1, + num_dvhs, path); GNUNET_free (path); } @@ -4704,6 +4719,7 @@ encapsulate_for_dv (struct DistanceVector *dv, dvh->next_hop, (const struct GNUNET_MessageHeader *) buf, options); + GNUNET_free (key); } return rtt; } @@ -4828,13 +4844,16 @@ route_control_message_without_fc (struct VirtualLink *vl, "Failed to route message, could not determine DV path\n"); return rtt1; } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "encapsulate_for_dv 1\n"); rtt2 = encapsulate_for_dv (dv, res, hops, hdr, &send_dv_to_neighbour, NULL, - options & (~RMO_REDUNDANT)); + options & (~RMO_REDUNDANT), + GNUNET_YES); } return GNUNET_TIME_relative_min (rtt1, rtt2); } @@ -4955,7 +4974,8 @@ check_vl_transmission (struct VirtualLink *vl) vl->outbound_fc_window_size) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Stalled transmission on VL %s due to flow control: %llu < %llu\n", + "Stalled message %lu transmission on VL %s due to flow control: %llu < %llu\n", + pm->logging_uuid, GNUNET_i2s (&vl->target), (unsigned long long) vl->outbound_fc_window_size, (unsigned long long) (pm->bytes_msg @@ -4964,6 +4984,14 @@ check_vl_transmission (struct VirtualLink *vl) return; /* We have a message, but flow control says "nope" */ } elig = GNUNET_YES; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Eligible message %lu of size %llu to %s: %llu/%llu\n", + pm->logging_uuid, + pm->bytes_msg, + GNUNET_i2s (&vl->target), + (unsigned long long) vl->outbound_fc_window_size, + (unsigned long long) (pm->bytes_msg + + vl->outbound_fc_window_size_used)); break; } if (GNUNET_NO == elig) @@ -5482,7 +5510,7 @@ handle_raw_message (void *cls, const struct GNUNET_MessageHeader *mh) vl->incoming_fc_window_size_used += size; /* TODO-M1 */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Dropped message of type %u with %u bytes to CORE: no CORE client connected!", + "Dropped message of type %u with %u bytes to CORE: no CORE client connected!\n", (unsigned int) ntohs (mh->type), (unsigned int) ntohs (mh->size)); finish_cmc_handling (cmc); @@ -5567,7 +5595,7 @@ transmit_cummulative_ack_cb (void *cls) struct VirtualLink *vl; struct AcknowledgementCummulator *ac = cls; char buf[sizeof(struct TransportReliabilityAckMessage) - + ac->ack_counter + ac->num_acks + + ac->num_acks * sizeof(struct TransportCummulativeAckPayloadP)] GNUNET_ALIGN; struct TransportReliabilityAckMessage *ack = (struct TransportReliabilityAckMessage *) buf; @@ -5576,16 +5604,16 @@ transmit_cummulative_ack_cb (void *cls) ac->task = NULL; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending ACK with %u components to %s\n", - ac->ack_counter, + ac->num_acks, GNUNET_i2s (&ac->target)); - GNUNET_assert (0 <= ac->ack_counter); + GNUNET_assert (0 < ac->num_acks); ack->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_ACK); ack->header.size = htons (sizeof(*ack) - + ac->ack_counter * sizeof(struct TransportCummulativeAckPayloadP)); + + ac->num_acks * sizeof(struct TransportCummulativeAckPayloadP)); ack->ack_counter = htonl (ac->ack_counter += ac->num_acks); ap = (struct TransportCummulativeAckPayloadP *) &ack[1]; - for (unsigned int i = 0; i < ac->ack_counter; i++) + for (unsigned int i = 0; i < ac->num_acks; i++) { ap[i].ack_uuid = ac->ack_uuids[i].ack_uuid; ap[i].ack_delay = GNUNET_TIME_relative_hton ( @@ -5657,7 +5685,6 @@ cummulative_ack (const struct GNUNET_PeerIdentity *pid, if (MAX_CUMMULATIVE_ACKS == ac->num_acks) { /* must run immediately, ack buffer full! */ - GNUNET_SCHEDULER_cancel (ac->task); transmit_cummulative_ack_cb (ac); } GNUNET_SCHEDULER_cancel (ac->task); @@ -5727,7 +5754,7 @@ static void handle_fragment_box (void *cls, const struct TransportFragmentBoxMessage *fb) { struct CommunicatorMessageContext *cmc = cls; - struct Neighbour *n; + struct VirtualLink *vl; struct ReassemblyContext *rc; const struct GNUNET_MessageHeader *msg; uint16_t msize; @@ -5737,30 +5764,33 @@ handle_fragment_box (void *cls, const struct TransportFragmentBoxMessage *fb) struct GNUNET_TIME_Relative cdelay; struct FindByMessageUuidContext fc; - n = lookup_neighbour (&cmc->im.sender); - if (NULL == n) + vl = lookup_virtual_link (&cmc->im.sender); + if (NULL == vl) { struct GNUNET_SERVICE_Client *client = cmc->tc->client; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "No virtual link for %s to handle fragment\n", + GNUNET_i2s (&cmc->im.sender)); GNUNET_break (0); finish_cmc_handling (cmc); GNUNET_SERVICE_client_drop (client); return; } - if (NULL == n->reassembly_map) + if (NULL == vl->reassembly_map) { - n->reassembly_map = GNUNET_CONTAINER_multihashmap32_create (8); - n->reassembly_heap = + vl->reassembly_map = GNUNET_CONTAINER_multihashmap32_create (8); + vl->reassembly_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN); - n->reassembly_timeout_task = + vl->reassembly_timeout_task = GNUNET_SCHEDULER_add_delayed (REASSEMBLY_EXPIRATION, &reassembly_cleanup_task, - n); + vl); } msize = ntohs (fb->msg_size); fc.message_uuid = fb->msg_uuid; fc.rc = NULL; - (void) GNUNET_CONTAINER_multihashmap32_get_multiple (n->reassembly_map, + (void) GNUNET_CONTAINER_multihashmap32_get_multiple (vl->reassembly_map, fb->msg_uuid.uuid, &find_by_message_uuid, &fc); @@ -5769,17 +5799,17 @@ handle_fragment_box (void *cls, const struct TransportFragmentBoxMessage *fb) rc = GNUNET_malloc (sizeof(*rc) + msize /* reassembly payload buffer */ + (msize + 7) / 8 * sizeof(uint8_t) /* bitfield */); rc->msg_uuid = fb->msg_uuid; - rc->neighbour = n; + rc->virtual_link = vl; rc->msg_size = msize; rc->reassembly_timeout = GNUNET_TIME_relative_to_absolute (REASSEMBLY_EXPIRATION); rc->last_frag = GNUNET_TIME_absolute_get (); - rc->hn = GNUNET_CONTAINER_heap_insert (n->reassembly_heap, + rc->hn = GNUNET_CONTAINER_heap_insert (vl->reassembly_heap, rc, rc->reassembly_timeout.abs_value_us); GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multihashmap32_put ( - n->reassembly_map, + vl->reassembly_map, rc->msg_uuid.uuid, rc, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)); @@ -6452,12 +6482,12 @@ learn_dv_path (const struct GNUNET_PeerIdentity *path, for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos; pos = pos->next_dv) { - if (pos->distance < path_len - 2) + if (pos->distance < path_len - 3) shorter_distance++; - /* Note that the distances in 'pos' excludes us (path[0]) and - the next_hop (path[1]), so we need to subtract two + /* Note that the distances in 'pos' excludes us (path[0]), + the next_hop (path[1]) and the target so we need to subtract three and check next_hop explicitly */ - if ((pos->distance == path_len - 2) && (pos->next_hop == next_hop)) + if ((pos->distance == path_len - 3) && (pos->next_hop == next_hop)) { int match = GNUNET_YES; @@ -6521,16 +6551,16 @@ learn_dv_path (const struct GNUNET_PeerIdentity *path, "Discovered new DV path to %s\n", GNUNET_i2s (&dv->target)); hop = GNUNET_malloc (sizeof(struct DistanceVectorHop) - + sizeof(struct GNUNET_PeerIdentity) * (path_len - 2)); + + sizeof(struct GNUNET_PeerIdentity) * (path_len - 3)); hop->next_hop = next_hop; hop->dv = dv; hop->path = (const struct GNUNET_PeerIdentity *) &hop[1]; memcpy (&hop[1], &path[2], - sizeof(struct GNUNET_PeerIdentity) * (path_len - 2)); + sizeof(struct GNUNET_PeerIdentity) * (path_len - 3)); hop->timeout = GNUNET_TIME_relative_to_absolute (DV_PATH_VALIDITY_TIMEOUT); hop->path_valid_until = path_valid_until; - hop->distance = path_len - 2; + hop->distance = path_len - 3; hop->pd.aged_rtt = network_latency; GNUNET_CONTAINER_MDLL_insert (dv, dv->dv_head, dv->dv_tail, hop); GNUNET_CONTAINER_MDLL_insert (neighbour, @@ -6630,6 +6660,7 @@ forward_dv_learn (const struct GNUNET_PeerIdentity *next_hop, fwd->init_sig = msg->init_sig; fwd->initiator = msg->initiator; fwd->challenge = msg->challenge; + fwd->monotonic_time = msg->monotonic_time; dhops = (struct DVPathEntryP *) &fwd[1]; GNUNET_memcpy (dhops, hops, sizeof(struct DVPathEntryP) * nhops); dhops[nhops].hop = GST_my_identity; @@ -6795,6 +6826,9 @@ dv_neighbour_transmission (void *cls, { struct NeighbourSelectionContext *nsc = cls; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "transmission %s\n", + GNUNET_i2s (pid)); (void) value; if (0 == GNUNET_memcmp (pid, &nsc->dvl->initiator)) return GNUNET_YES; /* skip initiator */ @@ -7012,7 +7046,7 @@ handle_dv_learn (void *cls, const struct TransportDVLearnMessage *dvl) &dvl->init_sig)) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "DV learn signature from %s invalid", + "DV learn signature from %s invalid\n", GNUNET_i2s (&dvl->initiator)); GNUNET_break_op (0); return; @@ -7141,7 +7175,7 @@ handle_dv_learn (void *cls, const struct TransportDVLearnMessage *dvl) GNUNET_i2s (&path[i]), GNUNET_STRINGS_relative_time_to_string (ilat, GNUNET_YES)); learn_dv_path (path, - i, + i + 1, ilat, GNUNET_TIME_relative_to_absolute ( ADDRESS_VALIDATION_LIFETIME)); @@ -7177,10 +7211,10 @@ handle_dv_learn (void *cls, const struct TransportDVLearnMessage *dvl) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Learned inverse path with %u hops to %s\n", - i + 1, + i + 2, GNUNET_i2s (&path[i + 2])); iret = learn_dv_path (path, - i + 2, + i + 3, GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_TIME_UNIT_ZERO_ABS); if (GNUNET_SYSERR == iret) @@ -7218,13 +7252,10 @@ handle_dv_learn (void *cls, const struct TransportDVLearnMessage *dvl) return; } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "8 handle dv learn message from %s\n", - GNUNET_i2s (&dvl->initiator)); /* Forward to initiator, if path non-trivial and possible */ bi_history = (bi_history << 1) | (bi_hop ? 1 : 0); did_initiator = GNUNET_NO; - if ((1 < nhops) && + if ((1 <= nhops) && (GNUNET_YES == GNUNET_CONTAINER_multipeermap_contains (neighbours, &dvl->initiator))) { @@ -7327,7 +7358,7 @@ check_dv_box (void *cls, const struct TransportDVBoxMessage *dvb) */ static void forward_dv_box (struct Neighbour *next_hop, - const struct TransportDVBoxMessage *hdr, + struct TransportDVBoxMessage *hdr, uint16_t total_hops, uint16_t num_hops, const struct GNUNET_PeerIdentity *hops, @@ -7336,37 +7367,57 @@ forward_dv_box (struct Neighbour *next_hop, { struct VirtualLink *vl = next_hop->vl; struct PendingMessage *pm; - size_t msg_size; + size_t msg_size = sizeof(struct TransportDVBoxMessage) + + num_hops * sizeof(struct GNUNET_PeerIdentity) + + enc_payload_size; char *buf; + char msg_buf[msg_size] GNUNET_ALIGN; struct GNUNET_PeerIdentity *dhops; - GNUNET_assert (NULL != vl); - msg_size = sizeof(struct TransportDVBoxMessage) - + num_hops * sizeof(struct GNUNET_PeerIdentity) + enc_payload_size; - pm = GNUNET_malloc (sizeof(struct PendingMessage) + msg_size); - pm->pmt = PMT_DV_BOX; - pm->vl = vl; - pm->timeout = GNUNET_TIME_relative_to_absolute (DV_FORWARD_TIMEOUT); - pm->logging_uuid = logging_uuid_gen++; - pm->prefs = GNUNET_MQ_PRIO_BACKGROUND; - pm->bytes_msg = msg_size; - buf = (char *) &pm[1]; - memcpy (buf, hdr, sizeof(*hdr)); - dhops = - (struct GNUNET_PeerIdentity *) &buf[sizeof(struct TransportDVBoxMessage)]; + GNUNET_assert (GNUNET_YES == ntohs (hdr->without_fc) || NULL != vl); + + hdr->num_hops = htons (num_hops); + hdr->total_hops = htons (total_hops); + memcpy (msg_buf, hdr, sizeof(*hdr)); + dhops = (struct GNUNET_PeerIdentity *) &msg_buf[sizeof(struct + TransportDVBoxMessage)]; memcpy (dhops, hops, num_hops * sizeof(struct GNUNET_PeerIdentity)); memcpy (&dhops[num_hops], enc_payload, enc_payload_size); - GNUNET_CONTAINER_MDLL_insert (vl, - vl->pending_msg_head, - vl->pending_msg_tail, - pm); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Created pending message %llu for DV Box with next hop %s (%u/%u)\n", - pm->logging_uuid, - GNUNET_i2s (&next_hop->pid), - (unsigned int) num_hops, - (unsigned int) total_hops); - check_vl_transmission (vl); + + if (GNUNET_YES == ntohs (hdr->without_fc)) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Forwarding control message in DV Box to next hop %s (%u/%u) \n", + GNUNET_i2s (&next_hop->pid), + (unsigned int) num_hops, + (unsigned int) total_hops); + route_via_neighbour (next_hop, (const struct + GNUNET_MessageHeader *) msg_buf, + RMO_ANYTHING_GOES); + } + else + { + pm = GNUNET_malloc (sizeof(struct PendingMessage) + msg_size); + pm->pmt = PMT_DV_BOX; + pm->vl = vl; + pm->timeout = GNUNET_TIME_relative_to_absolute (DV_FORWARD_TIMEOUT); + pm->logging_uuid = logging_uuid_gen++; + pm->prefs = GNUNET_MQ_PRIO_BACKGROUND; + pm->bytes_msg = msg_size; + buf = (char *) &pm[1]; + memcpy (buf, msg_buf, msg_size); + GNUNET_CONTAINER_MDLL_insert (vl, + vl->pending_msg_head, + vl->pending_msg_tail, + pm); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Created pending message %llu for DV Box with next hop %s (%u/%u)\n", + pm->logging_uuid, + GNUNET_i2s (&next_hop->pid), + (unsigned int) num_hops, + (unsigned int) total_hops); + check_vl_transmission (vl); + } } @@ -7579,11 +7630,14 @@ handle_dv_box (void *cls, const struct TransportDVBoxMessage *dvb) const char *enc_payload = (const char *) &hops[num_hops]; uint16_t enc_payload_size = size - (num_hops * sizeof(struct GNUNET_PeerIdentity)); - struct DVKeyState key; + char enc[enc_payload_size]; + struct DVKeyState *key; struct GNUNET_HashCode hmac; const char *hdr; size_t hdr_len; + key = GNUNET_new (struct DVKeyState); + if (GNUNET_EXTRA_LOGGING > 0) { char *path; @@ -7624,8 +7678,9 @@ handle_dv_box (void *cls, const struct TransportDVBoxMessage *dvb) "Skipping %u/%u hops ahead while routing DV Box\n", i, num_hops); + forward_dv_box (n, - dvb, + (struct TransportDVBoxMessage *) dvb, ntohs (dvb->total_hops) + 1, num_hops - i - 1, /* number of hops left */ &hops[i + 1], /* remaining hops */ @@ -7657,10 +7712,13 @@ handle_dv_box (void *cls, const struct TransportDVBoxMessage *dvb) GNUNET_NO); cmc->total_hops = ntohs (dvb->total_hops); - dh_key_derive_eph_pub (&dvb->ephemeral_key, &dvb->iv, &key); + dh_key_derive_eph_pub (&dvb->ephemeral_key, &dvb->iv, key); hdr = (const char *) &dvb[1]; - hdr_len = ntohs (dvb->header.size) - sizeof(*dvb); - dv_hmac (&key, &hmac, hdr, hdr_len); + hdr_len = ntohs (dvb->header.size) - sizeof(*dvb) - sizeof(struct + GNUNET_PeerIdentity) + * ntohs (dvb->total_hops); + + dv_hmac (key, &hmac, hdr, hdr_len); if (0 != GNUNET_memcmp (&hmac, &dvb->hmac)) { /* HMAC mismatch, discard! */ @@ -7679,9 +7737,9 @@ handle_dv_box (void *cls, const struct TransportDVBoxMessage *dvb) GNUNET_assert (hdr_len >= sizeof(ppay) + sizeof(struct GNUNET_MessageHeader)); - dv_decrypt (&key, &ppay, hdr, sizeof(ppay)); - dv_decrypt (&key, &body, &hdr[sizeof(ppay)], hdr_len - sizeof(ppay)); - dv_key_clean (&key); + dv_decrypt (key, &ppay, hdr, sizeof(ppay)); + dv_decrypt (key, &body, &hdr[sizeof(ppay)], hdr_len - sizeof(ppay)); + dv_key_clean (key); if (ntohs (mh->size) != sizeof(body)) { GNUNET_break_op (0); @@ -7727,9 +7785,10 @@ handle_dv_box (void *cls, const struct TransportDVBoxMessage *dvb) struct EphemeralConfirmationPS ec; ec.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL); - ec.purpose.size = htonl (sizeof(ec)); ec.target = GST_my_identity; ec.ephemeral_key = dvb->ephemeral_key; + ec.purpose.size = htonl (sizeof(ec)); + ec.sender_monotonic_time = ppay.monotonic_time; if ( GNUNET_OK != GNUNET_CRYPTO_eddsa_verify ( @@ -8656,6 +8715,12 @@ fragment_message (struct Queue *queue, mtu = (UINT16_MAX == queue->mtu) ? UINT16_MAX - sizeof(struct GNUNET_TRANSPORT_SendMessageTo) : queue->mtu; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Fragmenting message <%llu> with size %u to %s for MTU %u\n", + pm->logging_uuid, + pm->bytes_msg, + GNUNET_i2s (&pm->vl->target), + (unsigned int) mtu); set_pending_message_uuid (pm); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Fragmenting message %llu <%llu> with size %u to %s for MTU %u\n", @@ -8789,7 +8854,8 @@ reliability_box_message (struct Queue *queue, bpm->logging_uuid = logging_uuid_gen++; bpm->vl = pm->vl; bpm->frag_parent = pm; - GNUNET_CONTAINER_MDLL_insert (frag, pm->head_frag, pm->tail_frag, bpm); + // Why was this needed? + // GNUNET_CONTAINER_MDLL_insert (frag, pm->head_frag, pm->tail_frag, bpm); bpm->timeout = pm->timeout; bpm->pmt = PMT_RELIABILITY_BOX; bpm->bytes_msg = pm->bytes_msg + sizeof(rbox); @@ -8807,6 +8873,30 @@ reliability_box_message (struct Queue *queue, } +static void +reorder_root_pm (struct PendingMessage *pm, + struct GNUNET_TIME_Absolute next_attempt) +{ + struct VirtualLink *vl = pm->vl; + struct PendingMessage *pos; + + /* re-insert sort in neighbour list */ + GNUNET_CONTAINER_MDLL_remove (vl, + vl->pending_msg_head, + vl->pending_msg_tail, + pm); + pos = vl->pending_msg_tail; + while ((NULL != pos) && + (next_attempt.abs_value_us > pos->next_attempt.abs_value_us)) + pos = pos->prev_vl; + GNUNET_CONTAINER_MDLL_insert_after (vl, + vl->pending_msg_head, + vl->pending_msg_tail, + pos, + pm); +} + + /** * Change the value of the `next_attempt` field of @a pm * to @a next_attempt and re-order @a pm in the transmission @@ -8829,22 +8919,11 @@ update_pm_next_attempt (struct PendingMessage *pm, if (NULL == pm->frag_parent) { - struct PendingMessage *pos; - - /* re-insert sort in neighbour list */ - GNUNET_CONTAINER_MDLL_remove (vl, - vl->pending_msg_head, - vl->pending_msg_tail, - pm); - pos = vl->pending_msg_tail; - while ((NULL != pos) && - (next_attempt.abs_value_us > pos->next_attempt.abs_value_us)) - pos = pos->prev_vl; - GNUNET_CONTAINER_MDLL_insert_after (vl, - vl->pending_msg_head, - vl->pending_msg_tail, - pos, - pm); + reorder_root_pm (pm, next_attempt); + } + else if ((PMT_RELIABILITY_BOX == pm->pmt)||(PMT_DV_BOX == pm->pmt)) + { + reorder_root_pm (pm->frag_parent, next_attempt); } else { @@ -8862,6 +8941,15 @@ update_pm_next_attempt (struct PendingMessage *pm, fp->tail_frag, pos, pm); + if (NULL == pos) + { + pos = fp; + // Get the root pm + while (NULL != pos->frag_parent) + pos = pos->frag_parent; + pos->next_attempt = next_attempt; + reorder_root_pm (pos, next_attempt); + } } } @@ -8965,8 +9053,18 @@ select_best_pending_from_link (struct PendingMessageScoreContext *sc, (0 == (pos->prefs & GNUNET_MQ_PREF_UNRELIABLE)) && (GNUNET_TRANSPORT_CC_RELIABLE != queue->tc->details.communicator.cc)) { - relb = GNUNET_YES; real_overhead += sizeof(struct TransportReliabilityBoxMessage); + + if ((0 != queue->mtu) && (pos->bytes_msg + real_overhead > queue->mtu)) + { + frag = GNUNET_YES; + real_overhead = overhead + sizeof(struct TransportFragmentBoxMessage); + } + else + { + relb = GNUNET_YES; + } + } /* Finally, compare to existing 'best' in sc to see if this 'pos' pending @@ -8980,7 +9078,8 @@ select_best_pending_from_link (struct PendingMessageScoreContext *sc, given message fits _this_ queue, and do not consider how well other queues might suit the message. Taking other queues into consideration may further improve the result, but could also be expensive - in terms of CPU time. */long long sc_score = sc->frag * 40 + sc->relb * 20 + sc->real_overhead; + in terms of CPU time. */ + long long sc_score = sc->frag * 40 + sc->relb * 20 + sc->real_overhead; long long pm_score = frag * 40 + relb * 20 + real_overhead; long long time_delta = (sc->best->next_attempt.abs_value_us - pos->next_attempt.abs_value_us) @@ -8994,12 +9093,10 @@ select_best_pending_from_link (struct PendingMessageScoreContext *sc, time_delta *= 10; /* increase weight (always, both are low latency) */ else if ((0 != (pos->prefs & GNUNET_MQ_PREF_LOW_LATENCY)) && (time_delta > 0)) - time_delta *= - 10; /* increase weight, favors 'pos', which is low latency */ + time_delta *= 10; /* increase weight, favors 'pos', which is low latency */ else if ((0 != (sc->best->prefs & GNUNET_MQ_PREF_LOW_LATENCY)) && (time_delta < 0)) - time_delta *= - 10; /* increase weight, favors 'sc->best', which is low latency */ + time_delta *= 10; /* increase weight, favors 'sc->best', which is low latency */ if (0 != queue->mtu) { /* Grant bonus if we are below MTU, larger bonus the closer we will @@ -9016,6 +9113,7 @@ select_best_pending_from_link (struct PendingMessageScoreContext *sc, sc->dvh = dvh; sc->frag = frag; sc->relb = relb; + sc->real_overhead = real_overhead; } } @@ -9027,7 +9125,7 @@ select_best_pending_from_link (struct PendingMessageScoreContext *sc, * * @param cls a `struct PendingMessageScoreContext` * @param next_hop next hop of the DV path - * @param hdr encapsulated message, technically a `struct TransportDFBoxMessage` + * @param hdr encapsulated message, technically a `struct TransportDVBoxMessage` * @param options options of the original message */ static void @@ -9045,6 +9143,11 @@ extract_box_cb (void *cls, bpm = GNUNET_malloc (sizeof(struct PendingMessage) + bsize); bpm->logging_uuid = logging_uuid_gen++; bpm->pmt = PMT_DV_BOX; + bpm->vl = pm->vl; + bpm->timeout = pm->timeout; + bpm->bytes_msg = bsize; + bpm->frag_parent = pm; + set_pending_message_uuid (bpm); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating DV Box %llu for original message %llu (next hop is %s)\n", bpm->logging_uuid, @@ -9132,13 +9235,16 @@ transmit_on_queue (void *cls) free_pending_message (sc.best->bpm); sc.best->bpm = NULL; } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "encapsulate_for_dv 2\n"); encapsulate_for_dv (sc.dvh->dv, 1, &sc.dvh, (const struct GNUNET_MessageHeader *) &sc.best[1], &extract_box_cb, &sc, - RMO_NONE); + RMO_NONE, + GNUNET_NO); GNUNET_assert (NULL != sc.best->bpm); pm = sc.best->bpm; } @@ -9227,6 +9333,11 @@ transmit_on_queue (void *cls) OPTIMIZE: Note that in the future this heuristic should likely be improved further (measure RTT stability, consider message urgency and size when delaying ACKs, etc.) */ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Waiting %s for ACK\n", + GNUNET_STRINGS_relative_time_to_string ( + GNUNET_TIME_relative_multiply ( + queue->pd.aged_rtt, 4), GNUNET_NO)); update_pm_next_attempt (pm, GNUNET_TIME_relative_to_absolute ( GNUNET_TIME_relative_multiply (queue->pd.aged_rtt, diff --git a/src/transport/test_transport_distance_vector_topo.conf b/src/transport/test_transport_distance_vector_topo.conf new file mode 100644 index 000000000..ead3e0a0a --- /dev/null +++ b/src/transport/test_transport_distance_vector_topo.conf @@ -0,0 +1,8 @@ +M:2 +N:2 +X:0 +T:libgnunet_test_transport_plugin_cmd_simple_send_dv +R:1|{tcp_port:1}|{udp_port:0} +R:2|{tcp_port:1}|{udp_port:0} +P:1:1|{connect:{P:2:1:tcp}} +P:2:1|{connect:{P:1:1:tcp}} diff --git a/src/transport/test_transport_hmac_calculation.c b/src/transport/test_transport_hmac_calculation.c deleted file mode 100644 index 59f7e3d90..000000000 --- a/src/transport/test_transport_hmac_calculation.c +++ /dev/null @@ -1,250 +0,0 @@ -/* - This file is part of GNUnet. - Copyright (C) 2002-2015 GNUnet e.V. - - GNUnet is free software: you can redistribute it and/or modify it - under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, - or (at your option) any later version. - - GNUnet is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . - - SPDX-License-Identifier: AGPL3.0-or-later - - */ -/** - * @file util/test_crypto_ecdh_eddsa.c - * @brief testcase for ECC DH key exchange with EdDSA private keys. - * @author Christian Grothoff - * @author Bart Polot - */ -#include "platform.h" -#include "gnunet_util_lib.h" -#include - - -/** - * Structure of the key material used to encrypt backchannel messages. - */ -struct DVKeyState -{ - /** - * State of our block cipher. - */ - gcry_cipher_hd_t cipher; - - /** - * Actual key material. - */ - struct - { - /** - * Key used for HMAC calculations (via #GNUNET_CRYPTO_hmac()). - */ - struct GNUNET_CRYPTO_AuthKey hmac_key; - - /** - * Symmetric key to use for encryption. - */ - char aes_key[256 / 8]; - - /** - * Counter value to use during setup. - */ - char aes_ctr[128 / 8]; - } material; -}; - - -/** - * Given the key material in @a km and the initialization vector - * @a iv, setup the key material for the backchannel in @a key. - * - * @param km raw master secret - * @param iv initialization vector - * @param key[out] symmetric cipher and HMAC state to generate - */ -static void -dv_setup_key_state_from_km (const struct GNUNET_HashCode *km, - const struct GNUNET_ShortHashCode *iv, - struct DVKeyState *key) -{ - char *key_string; - - - /* must match #dh_key_derive_eph_pub */ - GNUNET_assert (GNUNET_YES == - GNUNET_CRYPTO_kdf (&key->material, - sizeof(key->material), - "transport-backchannel-key", - strlen ("transport-backchannel-key"), - &km, - sizeof(km), - iv, - sizeof(*iv), - NULL)); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Deriving backchannel key based on KM %s and IV %s\n", - GNUNET_h2s (km), - GNUNET_sh2s (iv)); - GNUNET_assert (0 == gcry_cipher_open (&key->cipher, - GCRY_CIPHER_AES256 /* low level: go for speed */, - GCRY_CIPHER_MODE_CTR, - 0 /* flags */)); - GNUNET_assert (0 == gcry_cipher_setkey (key->cipher, - &key->material.aes_key, - sizeof(key->material.aes_key))); - gcry_cipher_setctr (key->cipher, - &key->material.aes_ctr, - sizeof(key->material.aes_ctr)); - GNUNET_free (key_string); -} - - -/** - * Do HMAC calculation for backchannel messages over @a data using key - * material from @a key. - * - * @param key key material (from DH) - * @param hmac[out] set to the HMAC - * @param data data to perform HMAC calculation over - * @param data_size number of bytes in @a data - */ -static void -dv_hmac (const struct DVKeyState *key, - struct GNUNET_HashCode *hmac, - const void *data, - size_t data_size) -{ - GNUNET_CRYPTO_hmac (&key->material.hmac_key, data, data_size, hmac); -} - - -/** - * Clean up key material in @a key. - * - * @param key key material to clean up (memory must not be free'd!) - */ -static void -dv_key_clean (struct DVKeyState *key) -{ - gcry_cipher_close (key->cipher); - GNUNET_CRYPTO_zero_keys (&key->material, sizeof(key->material)); -} - - -static int -test_ecdh () -{ - struct GNUNET_CRYPTO_EddsaPrivateKey priv_dsa; - struct GNUNET_CRYPTO_EcdhePrivateKey priv_ecdh; - struct GNUNET_CRYPTO_EddsaPublicKey id1; - struct GNUNET_CRYPTO_EcdhePublicKey id2; - struct GNUNET_HashCode dh[2]; - struct DVKeyState *key[2]; - struct GNUNET_ShortHashCode iv; - struct GNUNET_HashCode hmac[2]; - char *enc = "test"; - char *key_string_1; - char *key_string_2; - - - key[0] = GNUNET_new (struct DVKeyState); - key[1] = GNUNET_new (struct DVKeyState); - GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE, - &iv, - sizeof(iv)); - - /* Generate keys */ - GNUNET_CRYPTO_eddsa_key_create (&priv_dsa); - GNUNET_CRYPTO_eddsa_key_get_public (&priv_dsa, - &id1); - - GNUNET_CRYPTO_ecdhe_key_create (&priv_ecdh); - /* Extract public keys */ - GNUNET_CRYPTO_ecdhe_key_get_public (&priv_ecdh, - &id2); - /* Do ECDH */ - GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_eddsa_ecdh (&priv_dsa, - &id2, - &dh[0])); - GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_ecdh_eddsa (&priv_ecdh, - &id1, - &dh[1])); - /* Check that both DH results are equal. */ - GNUNET_assert (0 == GNUNET_memcmp (&dh[0], - &dh[1])); - - dv_setup_key_state_from_km (&dh[0], - (const struct GNUNET_ShortHashCode *) &iv, - key[0]); - dv_hmac ((const struct DVKeyState * ) key[0], - &hmac[0], enc, - sizeof(enc)); - - dv_setup_key_state_from_km (&dh[1], - (const struct GNUNET_ShortHashCode *) &iv, - key[1]); - dv_hmac ((const struct DVKeyState *) key[1], - &hmac[1], - enc, - sizeof(enc)); - - key_string_1 = GNUNET_STRINGS_data_to_string_alloc (&key[0]->material.hmac_key, - sizeof (struct - GNUNET_CRYPTO_AuthKey)); - key_string_2 = GNUNET_STRINGS_data_to_string_alloc (&key[1]->material.hmac_key, - sizeof (struct GNUNET_CRYPTO_AuthKey)); - - if (0 != GNUNET_memcmp (key[0], key[1]) || 0 != GNUNET_memcmp (&hmac[0], &hmac[1])) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "first key %s\n", - key_string_1); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "second key %s\n", - key_string_2); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "first hmac %s\n", - GNUNET_h2s (&hmac[0])); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "second hmac %s\n", - GNUNET_h2s (&hmac[1])); - } - dv_key_clean (key[0]); - dv_key_clean (key[1]); - GNUNET_free (key_string_1); - GNUNET_free (key_string_2); - - return 0; -} - - -int -main (int argc, char *argv[]) -{ - if (! gcry_check_version ("1.6.0")) - { - fprintf (stderr, - _ ( - "libgcrypt has not the expected version (version %s is required).\n"), - "1.6.0"); - return 0; - } - if (getenv ("GNUNET_GCRYPT_DEBUG")) - gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u, 0); - GNUNET_log_setup ("test-transport-hmac-calculation", "DEBUG", NULL); - if (0 != test_ecdh ()) - return 1; - - return 0; -} - - -/* end of test_crypto_ecdh_eddsa.c */ diff --git a/src/transport/test_transport_plugin_cmd_simple_send_dv.c b/src/transport/test_transport_plugin_cmd_simple_send_dv.c index e73e5a0b2..167120e2b 100644 --- a/src/transport/test_transport_plugin_cmd_simple_send_dv.c +++ b/src/transport/test_transport_plugin_cmd_simple_send_dv.c @@ -64,6 +64,12 @@ struct TestState * The complete topology information. */ struct GNUNET_TESTING_NetjailTopology *topology; + + /** + * The number of messages received. + */ + unsigned int number_received; + }; static struct GNUNET_TESTING_Command block_send; @@ -74,6 +80,8 @@ static struct GNUNET_TESTING_Command connect_peers; static struct GNUNET_TESTING_Command local_prepared; +static struct GNUNET_TESTING_Command start_peer; + /** * Function called to check a message of type GNUNET_TRANSPORT_TESTING_SIMPLE_MTYPE being * received. @@ -83,6 +91,7 @@ static int check_test (void *cls, const struct GNUNET_TRANSPORT_TESTING_TestMessage *message) { + GNUNET_assert (NULL != cls); return GNUNET_OK; } @@ -96,17 +105,52 @@ static void handle_test (void *cls, const struct GNUNET_TRANSPORT_TESTING_TestMessage *message) { - const struct GNUNET_TESTING_AsyncContext *ac; + struct TestState *ts = cls; + const struct GNUNET_TESTING_AsyncContext *ac_block; + const struct GNUNET_TESTING_AsyncContext *ac_start; + const struct GNUNET_TESTING_Command *cmd; + const struct GNUNET_CONTAINER_MultiShortmap *connected_peers_map; + unsigned int connected; + struct BlockState *bs; + + + GNUNET_TRANSPORT_get_trait_connected_peers_map (&start_peer, + &connected_peers_map); + + connected = GNUNET_CONTAINER_multishortmap_size ( + connected_peers_map); + + ts->number_received++; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Received test message\n"); + "Received %u test message(s) from %u connected peer(s)\n", + ts->number_received, + connected); + GNUNET_TESTING_get_trait_async_context (&block_receive, - &ac); - GNUNET_assert (NULL != ac); - if (NULL == ac->cont) - GNUNET_TESTING_async_fail ((struct GNUNET_TESTING_AsyncContext *) ac); - else - GNUNET_TESTING_async_finish ((struct GNUNET_TESTING_AsyncContext *) ac); + &ac_block); + + if ( connected == ts->number_received) + { + if (NULL != ac_block->is) + { + GNUNET_assert (NULL != ac_block); + if (NULL == ac_block->cont) + GNUNET_TESTING_async_fail ((struct + GNUNET_TESTING_AsyncContext *) ac_block); + else + GNUNET_TESTING_async_finish ((struct + GNUNET_TESTING_AsyncContext *) ac_block); + } + else + { + GNUNET_TESTING_get_trait_block_state ( + &block_receive, + (const struct BlockState **) &bs); + bs->asynchronous_finish = GNUNET_YES; + } + + } } @@ -232,8 +276,17 @@ start_testcase (TESTING_CMD_HELPER_write_cb write_message, char *router_ip, unsigned int num; struct TestState *ts = GNUNET_new (struct TestState); struct GNUNET_TESTING_NetjailTopology *topology; + struct GNUNET_MQ_MessageHandler handlers[] = { + GNUNET_MQ_hd_var_size (test, + GNUNET_TRANSPORT_TESTING_SIMPLE_MTYPE, + struct GNUNET_TRANSPORT_TESTING_TestMessage, + ts), + GNUNET_MQ_handler_end () + }; - + LOG (GNUNET_ERROR_TYPE_DEBUG, + "number_received %u\n", + ts->number_received); if (GNUNET_YES == *read_file) { @@ -258,12 +311,13 @@ start_testcase (TESTING_CMD_HELPER_write_cb write_message, char *router_ip, block_send = GNUNET_TESTING_cmd_block_until_external_trigger ("block"); block_receive = GNUNET_TESTING_cmd_block_until_external_trigger ( "block-receive"); - connect_peers = GNUNET_TRANSPORT_cmd_connect_peers ("connect-peers", - "start-peer", - "system-create", - num, - topology, - 8); + connect_peers = GNUNET_TRANSPORT_cmd_connect_peers ( + "connect-peers", + "start-peer", + "system-create", + num, + topology, + topology->additional_connects); local_prepared = GNUNET_TESTING_cmd_local_test_prepared ( "local-test-prepared", write_message); @@ -286,25 +340,18 @@ start_testcase (TESTING_CMD_HELPER_write_cb write_message, char *router_ip, m, n); - struct GNUNET_MQ_MessageHandler handlers[] = { - GNUNET_MQ_hd_var_size (test, - GNUNET_TRANSPORT_TESTING_SIMPLE_MTYPE, - struct GNUNET_TRANSPORT_TESTING_TestMessage, - ts), - GNUNET_MQ_handler_end () - }; - + start_peer = GNUNET_TRANSPORT_cmd_start_peer ("start-peer", + "system-create", + num, + node_ip, + handlers, + ts->cfgname, + notify_connect, + GNUNET_YES); struct GNUNET_TESTING_Command commands[] = { GNUNET_TESTING_cmd_system_create ("system-create", ts->testdir), - GNUNET_TRANSPORT_cmd_start_peer ("start-peer", - "system-create", - num, - node_ip, - handlers, - ts->cfgname, - notify_connect, - GNUNET_YES), + start_peer, GNUNET_TESTING_cmd_send_peer_ready ("send-peer-ready", write_message), block_send, diff --git a/src/transport/test_transport_simple_send_dv_circle.sh b/src/transport/test_transport_simple_send_dv_circle.sh new file mode 100755 index 000000000..de16df356 --- /dev/null +++ b/src/transport/test_transport_simple_send_dv_circle.sh @@ -0,0 +1,12 @@ +#!/bin/bash +if ! [ -d "/run/netns" ]; then + echo You have to create the directory /run/netns. +fi +if [ "$(cat /proc/sys/kernel/unprivileged_userns_clone)" == 1 ]; then + # exec unshare -r -nmU bash -c "mount -t tmpfs --make-rshared tmpfs /run/netns; valgrind --leak-check=full --track-origins=yes --trace-children=yes --trace-children-skip=/usr/bin/awk,/usr/bin/cut,/usr/bin/seq,/sbin/ip/sed/bash ./test_transport_start_with_config test_transport_distance_vector_topo.conf" + exec unshare -r -nmU bash -c "mount -t tmpfs --make-rshared tmpfs /run/netns; ./test_transport_start_with_config test_transport_distance_vector_circle_topo.conf" + #./test_transport_start_with_config test_transport_distance_vector_circle_topo.conf +else + echo -e "Error during test setup: The kernel parameter kernel.unprivileged_userns_clone has to be set to 1! One has to execute\n\n sysctl kernel.unprivileged_userns_clone=1\n" + exit 78 +fi diff --git a/src/transport/transport-testing-cmds.h b/src/transport/transport-testing-cmds.h index af6f47962..5a3fb22d6 100644 --- a/src/transport/transport-testing-cmds.h +++ b/src/transport/transport-testing-cmds.h @@ -187,7 +187,7 @@ struct StartPeerState /** * Flag indicating, if udp broadcast should be switched on. */ - unsigned int broadcast; + enum GNUNET_GenericReturnValue broadcast; }; @@ -337,7 +337,8 @@ GNUNET_TRANSPORT_cmd_backchannel_check (const char *label, op (hello, const char) \ op (application_handle, const struct GNUNET_TRANSPORT_ApplicationHandle) \ op (connect_peer_state, const struct ConnectPeersState) \ - op (state, const struct StartPeerState) + op (state, const struct StartPeerState) \ + op (broadcast, const enum GNUNET_GenericReturnValue) GNUNET_TRANSPORT_SIMPLE_TRAITS (GNUNET_TRANSPORT_MAKE_DECL_SIMPLE_TRAIT) diff --git a/src/transport/transport_api_cmd_connecting_peers.c b/src/transport/transport_api_cmd_connecting_peers.c index fc925675d..296a98147 100644 --- a/src/transport/transport_api_cmd_connecting_peers.c +++ b/src/transport/transport_api_cmd_connecting_peers.c @@ -54,17 +54,25 @@ connect_peers_run (void *cls, const struct GNUNET_TRANSPORT_ApplicationHandle *ah; struct GNUNET_PeerIdentity *peer; char *addr; + char *addr_and_port; enum GNUNET_NetworkType nt = 0; uint32_t num; struct GNUNET_TESTING_NodeConnection *pos_connection; struct GNUNET_TESTING_AddressPrefix *pos_prefix; unsigned int con_num = 0; + const enum GNUNET_GenericReturnValue *broadcast; + const enum GNUNET_GenericReturnValue *broadcast_pointer; + char *port; cps->is = is; peer1_cmd = GNUNET_TESTING_interpreter_lookup_command (is, cps->start_peer_label); GNUNET_TRANSPORT_get_trait_application_handle (peer1_cmd, &ah); + GNUNET_TRANSPORT_get_trait_broadcast (peer1_cmd, + &broadcast); + + // broadcast = *broadcast_pointer; system_cmd = GNUNET_TESTING_interpreter_lookup_command (is, cps->create_label); @@ -93,19 +101,38 @@ connect_peers_run (void *cls, pos_prefix->address_prefix); if (NULL != addr) { + if (0 == GNUNET_memcmp (pos_prefix->address_prefix, "udp")) + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "validating memcmp\n"); + if (GNUNET_YES == *broadcast) + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "validating broadcast\n"); + if ((0 == GNUNET_memcmp (pos_prefix->address_prefix, "udp")) && + (GNUNET_YES == *broadcast) ) + GNUNET_asprintf (&addr_and_port, + "%s:2086", + addr); + else + GNUNET_asprintf (&addr_and_port, + "%s:60002", + addr); peer = GNUNET_TESTING_get_pub_key (num, tl_system); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "validating peer number %u with identity %s\n", + "validating peer number %u with identity %s and address %s %u %s\n", num, - GNUNET_i2s (peer)); + GNUNET_i2s (peer), + addr_and_port, + *broadcast, + pos_prefix->address_prefix); GNUNET_TRANSPORT_application_validate ((struct GNUNET_TRANSPORT_ApplicationHandle *) ah, peer, nt, - addr); + addr_and_port); GNUNET_free (peer); GNUNET_free (addr); + GNUNET_free (addr_and_port); } } } @@ -146,6 +173,12 @@ notify_connect (struct GNUNET_TESTING_Interpreter *is, if (cps->con_num == con_num) cps->additional_connects_notified++; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "con_num: %u add: %u num_notified: %u add_notified: %u\n", + cps->con_num, + cps->additional_connects, + cps->con_num_notified, + cps->additional_connects_notified); if (cps->con_num + cps->additional_connects == cps->con_num_notified + cps->additional_connects_notified) { diff --git a/src/transport/transport_api_cmd_start_peer.c b/src/transport/transport_api_cmd_start_peer.c index be2ea25b4..e305e24e1 100644 --- a/src/transport/transport_api_cmd_start_peer.c +++ b/src/transport/transport_api_cmd_start_peer.c @@ -124,7 +124,7 @@ notify_connect (void *cls, struct GNUNET_HashCode hc; struct GNUNET_CRYPTO_EddsaPublicKey public_key = peer->public_key; - void *ret = NULL; + void *ret = sps->handlers; LOG (GNUNET_ERROR_TYPE_DEBUG, "This Peer %s \n", @@ -150,7 +150,6 @@ notify_connect (void *cls, sps->notify_connect (sps->ac.is, peer); - // TODO what does the handler function need? return ret; } @@ -418,6 +417,7 @@ start_peer_traits (void *cls, GNUNET_TRANSPORT_make_trait_hello ((const void *) hello), GNUNET_TRANSPORT_make_trait_hello_size ((const void *) hello_size), GNUNET_TRANSPORT_make_trait_state ((const void *) sps), + GNUNET_TRANSPORT_make_trait_broadcast ((const void *) &sps->broadcast), GNUNET_TESTING_trait_end () }; -- cgit v1.2.3