From 6b83e9a453ffc9ea0347a7e725c3a9b6d2a32517 Mon Sep 17 00:00:00 2001 From: t3sserakt Date: Wed, 8 Feb 2023 10:37:33 +0100 Subject: TNG: Added performance test case. --- src/transport/Makefile.am | 23 +- ..._transport_plugin_cmd_simple_send_performance.c | 508 +++++++++++++++++++++ .../test_transport_simple_send_performance.sh | 11 + ...est_transport_simple_send_performance_topo.conf | 6 + src/transport/transport-testing-cmds.h | 22 + src/transport/transport-testing2.h | 23 + .../transport_api_cmd_send_simple_performance.c | 219 +++++++++ 7 files changed, 811 insertions(+), 1 deletion(-) create mode 100644 src/transport/test_transport_plugin_cmd_simple_send_performance.c create mode 100755 src/transport/test_transport_simple_send_performance.sh create mode 100644 src/transport/test_transport_simple_send_performance_topo.conf create mode 100644 src/transport/transport_api_cmd_send_simple_performance.c (limited to 'src') diff --git a/src/transport/Makefile.am b/src/transport/Makefile.am index 5acba3a4e..eeafab840 100644 --- a/src/transport/Makefile.am +++ b/src/transport/Makefile.am @@ -130,6 +130,7 @@ libgnunettransporttesting2_la_SOURCES = \ transport_api_cmd_start_peer.c \ transport_api_cmd_stop_peer.c \ transport_api_cmd_send_simple.c \ + transport_api_cmd_send_simple_performance.c \ transport-testing2.c transport-testing2.h \ transport-testing-cmds.h \ transport-testing-filenames2.c \ @@ -357,6 +358,7 @@ plugin_LTLIBRARIES = \ $(HTTPS_SERVER_PLUGIN_LA) \ $(WLAN_PLUGIN_LA) \ $(BT_PLUGIN_LA) \ + libgnunet_test_transport_plugin_cmd_simple_send_performance.la \ libgnunet_test_transport_plugin_cmd_nat_upnp.la \ libgnunet_test_transport_plugin_cmd_simple_send.la \ libgnunet_test_transport_plugin_cmd_simple_send_broadcast.la \ @@ -414,6 +416,23 @@ libgnunet_test_transport_plugin_cmd_simple_send_la_LIBADD = \ libgnunet_test_transport_plugin_cmd_simple_send_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) +libgnunet_test_transport_plugin_cmd_simple_send_performance_la_SOURCES = \ + test_transport_plugin_cmd_simple_send_performance.c +libgnunet_test_transport_plugin_cmd_simple_send_performance_la_LIBADD = \ + libgnunettransporttesting2.la \ + libgnunettransportapplication.la \ + libgnunettransportcore.la \ + $(top_builddir)/src/testing/libgnunettesting.la \ + $(top_builddir)/src/peerstore/libgnunetpeerstore.la \ + $(top_builddir)/src/statistics/libgnunetstatistics.la \ + $(top_builddir)/src/hello/libgnunethello.la \ + $(top_builddir)/src/ats/libgnunetats.la \ + $(top_builddir)/src/arm/libgnunetarm.la \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(LTLIBINTL) +libgnunet_test_transport_plugin_cmd_simple_send_performance_la_LDFLAGS = \ + $(GN_PLUGIN_LDFLAGS) + libgnunet_test_transport_plugin_cmd_simple_send_broadcast_la_SOURCES = \ test_transport_plugin_cmd_simple_send_broadcast.c libgnunet_test_transport_plugin_cmd_simple_send_broadcast_la_LIBADD = \ @@ -760,7 +779,8 @@ endif # Only test TNG if we run experimental if HAVE_EXPERIMENTAL check_SCRIPTS= \ -test_transport_nat_icmp_tcp.sh \ + test_transport_simple_send_performance.sh \ + test_transport_nat_icmp_tcp.sh \ test_transport_nat_upnp.sh \ test_transport_simple_send_string.sh \ test_transport_simple_send.sh \ @@ -1510,6 +1530,7 @@ test_transport_api_slow_ats_LDADD = \ EXTRA_DIST = \ +test_transport_simple_send_performance.sh \ test_transport_nat_icmp_tcp.sh \ test_transport_nat_upnp.sh \ test_transport_simple_send_string.sh \ diff --git a/src/transport/test_transport_plugin_cmd_simple_send_performance.c b/src/transport/test_transport_plugin_cmd_simple_send_performance.c new file mode 100644 index 000000000..17325e369 --- /dev/null +++ b/src/transport/test_transport_plugin_cmd_simple_send_performance.c @@ -0,0 +1,508 @@ +/* + This file is part of GNUnet + Copyright (C) 2021 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 testbed/plugin_cmd_simple_send.c + * @brief a plugin to provide the API for running test cases. + * @author t3sserakt + */ +#include "platform.h" +#include "gnunet_testing_barrier.h" +#include "gnunet_testing_netjail_lib.h" +#include "gnunet_util_lib.h" +#include "gnunet_transport_application_service.h" +#include "transport-testing2.h" +#include "transport-testing-cmds.h" +#include "gnunet_testing_barrier.h" + +/** + * Generic logging shortcut + */ +#define LOG(kind, ...) GNUNET_log (kind, __VA_ARGS__) + +#define BASE_DIR "testdir" + +#define TOPOLOGY_CONFIG "test_transport_simple_send_topo.conf" + +#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 600) + +#define MAX_RECEIVED 1000 + +#define MESSAGE_SIZE 65000 + +static struct GNUNET_TESTING_Command block_send; + +static struct GNUNET_TESTING_Command block_receive; + +static struct GNUNET_TESTING_Command connect_peers; + +static struct GNUNET_TESTING_Command local_prepared; + +static struct GNUNET_TESTING_Command start_peer; + +static struct GNUNET_TESTING_Interpreter *is; + +static struct GNUNET_CONTAINER_MultiPeerMap *senders; + +struct Sender +{ + /** + * Number of received messages from sender. + */ + unsigned long long num_received; + + /** + * Sample mean time the message traveled. + */ + struct GNUNET_TIME_Relative mean_time; + + /** + * Time the first message was send. + */ + struct GNUNET_TIME_Absolute time_first; +}; + +/** + * Function called to check a message of type GNUNET_TRANSPORT_TESTING_SIMPLE_MTYPE being + * received. + * + */ +static int +check_test (void *cls, + const struct GNUNET_TRANSPORT_TESTING_PerformanceTestMessage *message) +{ + return GNUNET_OK; +} + + +/** + * Function called to handle a message of type GNUNET_TRANSPORT_TESTING_SIMPLE_MTYPE + * being received. + * + */ +static void +handle_test (void *cls, + const struct GNUNET_TRANSPORT_TESTING_PerformanceTestMessage *message) +{ + struct GNUNET_PeerIdentity *peer = cls; + const struct GNUNET_TESTING_AsyncContext *ac; + struct Sender *sender; + struct GNUNET_TIME_Absolute time_send; + struct GNUNET_TIME_Absolute now; + struct GNUNET_TIME_Relative time_traveled; + uint32_t num; + struct GNUNET_TRANSPORT_CoreHandle *ch; + const struct StartPeerState *sps; + + + GNUNET_TRANSPORT_get_trait_state (&start_peer, + &sps); + ch = sps->th; + num = ntohl (message->num); + GNUNET_TESTING_get_trait_async_context (&block_receive, + &ac); + GNUNET_assert (NULL != ac); + + sender = GNUNET_CONTAINER_multipeermap_get (senders, peer); + + now = GNUNET_TIME_absolute_get (); + time_send = GNUNET_TIME_absolute_ntoh (message->time_send); + + time_traveled = GNUNET_TIME_absolute_get_difference (time_send, now); + + if (NULL == sender) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "time traveled init %s\n", + GNUNET_i2s(peer)); + sender = GNUNET_new (struct Sender); + sender->time_first = time_send; + sender->mean_time = GNUNET_TIME_UNIT_ZERO; + GNUNET_CONTAINER_multipeermap_put (senders, peer, sender, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); + } + + if (GNUNET_TIME_UNIT_ZERO.rel_value_us == sender->mean_time.rel_value_us) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "time traveld mean zero\n"); + sender->mean_time = time_traveled; + } + else + { + double factor = sender->num_received/(sender->num_received + 1); + struct GNUNET_TIME_Relative s1; + struct GNUNET_TIME_Relative s2; + + s1 = GNUNET_TIME_relative_multiply (sender->mean_time, + factor); + s2 = GNUNET_TIME_relative_divide (time_traveled, + sender->num_received + 1); + sender->mean_time = GNUNET_TIME_relative_add (s1, s2); + } + + sender->num_received++; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "time traveled: %llu\n", + time_traveled.rel_value_us); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "mean time traveled: %s %llu messages received with message number %u\n", + GNUNET_STRINGS_relative_time_to_string (sender->mean_time, GNUNET_NO), + sender->num_received, + num); + if (MAX_RECEIVED <= sender->num_received && NULL == ac->cont) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "time traveled failed\n"); + GNUNET_TESTING_async_fail ((struct GNUNET_TESTING_AsyncContext *) ac); + } + else if (MAX_RECEIVED <= sender->num_received) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "time traveled finish\n"); + GNUNET_TESTING_async_finish ((struct GNUNET_TESTING_AsyncContext *) ac); + } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "time traveled end\n"); + GNUNET_TRANSPORT_core_receive_continue (ch, peer); +} + + +struct GNUNET_TESTING_BarrierList* +get_waiting_for_barriers () +{ + struct GNUNET_TESTING_BarrierList* barriers; + struct GNUNET_TESTING_BarrierListEntry *ble; + + barriers = GNUNET_new (struct GNUNET_TESTING_BarrierList); + ble = GNUNET_new (struct GNUNET_TESTING_BarrierListEntry); + ble->barrier_name = "ready-to-connect"; + ble->expected_reaches = 1; + GNUNET_CONTAINER_DLL_insert (barriers->head, + barriers->tail, + ble); + + ble = GNUNET_new (struct GNUNET_TESTING_BarrierListEntry); + ble->barrier_name = "test-case-finished"; + ble->expected_reaches = 1; + GNUNET_CONTAINER_DLL_insert (barriers->head, + barriers->tail, + ble); + return barriers; +} + + +/** + * Callback to set the flag indicating all peers started. Will be called via the plugin api. + * + */ +static void +all_peers_started () +{ + const struct GNUNET_TESTING_AsyncContext *ac; + + GNUNET_TESTING_get_trait_async_context (&block_send, + &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); +} + + +/** + * Function called with the final result of the test. + * + * @param cls the `struct MainParams` + * @param rv #GNUNET_OK if the test passed + */ +static void +handle_result (void *cls, + enum GNUNET_GenericReturnValue rv) +{ + struct TestState *ts = cls; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Local test exits with status %d\n", + rv); + + ts->finished_cb (rv); + GNUNET_free (ts->testdir); + GNUNET_free (ts->cfgname); + GNUNET_TESTING_free_topology (ts->topology); + GNUNET_free (ts); +} + + +/** + * Callback from start peer cmd for signaling a peer got connected. + * + */ +static void * +notify_connect (struct GNUNET_TESTING_Interpreter *is, + const struct GNUNET_PeerIdentity *peer) +{ + const struct ConnectPeersState *cps; + const struct GNUNET_TESTING_Command *cmd; + + cmd = GNUNET_TESTING_interpreter_lookup_command (is, + "connect-peers"); + GNUNET_TRANSPORT_get_trait_connect_peer_state (cmd, + &cps); + void *ret = NULL; + + cps->notify_connect (is, + peer); + return ret; +} + + +/** + * Callback to set the flag indicating all peers are prepared to finish. Will be called via the plugin api. + */ +static void +all_local_tests_prepared () +{ + const struct GNUNET_TESTING_LocalPreparedState *lfs; + + GNUNET_TESTING_get_trait_local_prepared_state (&local_prepared, + &lfs); + GNUNET_assert (NULL != &lfs->ac); + if (NULL == lfs->ac.cont) + GNUNET_TESTING_async_fail ((struct GNUNET_TESTING_AsyncContext *) &lfs->ac); + else + GNUNET_TESTING_async_finish ((struct + GNUNET_TESTING_AsyncContext *) &lfs->ac); +} + + +/** + * Function to start a local test case. + * + * @param write_message Callback to send a message to the master loop. + * @param router_ip Global address of the network namespace. + * @param node_ip The IP address of the node. + * @param m The number of the node in a network namespace. + * @param n The number of the network namespace. + * @param local_m The number of nodes in a network namespace. + * @param topology_data A file name for the file containing the topology configuration, or a string containing + * the topology configuration. + * @param read_file If read_file is GNUNET_YES this string is the filename for the topology configuration, + * if read_file is GNUNET_NO the string contains the topology configuration. + * @param finish_cb Callback function which writes a message from the helper process running on a netjail + * node to the master process * signaling that the test case running on the netjail node finished. + * @return Returns the struct GNUNET_TESTING_Interpreter of the command loop running on this netjail node. + */ +static struct GNUNET_TESTING_Interpreter * +start_testcase (GNUNET_TESTING_cmd_helper_write_cb write_message, + const char *router_ip, + const char *node_ip, + const char *m, + const char *n, + const char *local_m, + const char *topology_data, + unsigned int *read_file, + GNUNET_TESTING_cmd_helper_finish_cb finished_cb) +{ + + unsigned int n_int; + unsigned int m_int; + unsigned int local_m_int; + unsigned int num; + struct TestState *ts = GNUNET_new (struct TestState); + struct GNUNET_TESTING_NetjailTopology *topology; + unsigned int sscanf_ret = 0; + + senders = GNUNET_CONTAINER_multipeermap_create (1, GNUNET_NO); + ts->finished_cb = finished_cb; + LOG (GNUNET_ERROR_TYPE_ERROR, + "n %s m %s\n", + n, + m); + + if (GNUNET_YES == *read_file) + { + LOG (GNUNET_ERROR_TYPE_DEBUG, + "read from file\n"); + topology = GNUNET_TESTING_get_topo_from_file (topology_data); + } + else + topology = GNUNET_TESTING_get_topo_from_string (topology_data); + + ts->topology = topology; + + errno = 0; + sscanf_ret = sscanf (m, "%u", &m_int); + if (errno != 0) + { + GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "sscanf"); + } + GNUNET_assert (0 < sscanf_ret); + errno = 0; + sscanf_ret = sscanf (n, "%u", &n_int); + if (errno != 0) + { + GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "sscanf"); + } + GNUNET_assert (0 < sscanf_ret); + errno = 0; + sscanf_ret = sscanf (local_m, "%u", &local_m_int); + if (errno != 0) + { + GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "sscanf"); + } + GNUNET_assert (0 < sscanf_ret); + + if (0 == n_int) + num = m_int; + else + num = (n_int - 1) * local_m_int + m_int + topology->nodes_x; + + 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, + 0); + local_prepared = GNUNET_TESTING_cmd_local_test_prepared ( + "local-test-prepared", + write_message); + + + GNUNET_asprintf (&ts->cfgname, + "test_transport_api2_tcp_node1.conf"); + + LOG (GNUNET_ERROR_TYPE_DEBUG, + "plugin cfgname: %s\n", + ts->cfgname); + + LOG (GNUNET_ERROR_TYPE_DEBUG, + "node ip: %s\n", + node_ip); + + GNUNET_asprintf (&ts->testdir, + "%s%s%s", + BASE_DIR, + m, + n); + + struct GNUNET_MQ_MessageHandler handlers[] = { + GNUNET_MQ_hd_var_size (test, + GNUNET_TRANSPORT_TESTING_SIMPLE_PERFORMANCE_MTYPE, + struct GNUNET_TRANSPORT_TESTING_PerformanceTestMessage, + 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_NO); + + struct GNUNET_TESTING_Command commands[] = { + GNUNET_TESTING_cmd_system_create ("system-create", + ts->testdir), + start_peer, + GNUNET_TESTING_cmd_barrier_reached ("ready-to-connect-reached", + "ready-to-connect", + GNUNET_NO, + num, + GNUNET_NO, + write_message), + connect_peers, + GNUNET_TRANSPORT_cmd_send_simple_performance ("send-simple", + "start-peer", + "system-create", + num, + MESSAGE_SIZE, + MAX_RECEIVED, + topology), + block_receive, + GNUNET_TESTING_cmd_barrier_reached ("test-case-finished-reached", + "test-case-finished", + GNUNET_NO, + num, + GNUNET_NO, + write_message), + GNUNET_TRANSPORT_cmd_stop_peer ("stop-peer", + "start-peer"), + GNUNET_TESTING_cmd_system_destroy ("system-destroy", + "system-create"), + GNUNET_TESTING_cmd_end () + }; + + ts->write_message = write_message; + + is = GNUNET_TESTING_run (commands, + TIMEOUT, + &handle_result, + ts); + return is; +} + + +/** + * Entry point for the plugin. + * + * @param cls NULL + * @return the exported block API + */ +void * +libgnunet_test_transport_plugin_cmd_simple_send_performance_init (void *cls) +{ + struct GNUNET_TESTING_PluginFunctions *api; + + GNUNET_log_setup ("simple-send", + "DEBUG", + NULL); + + api = GNUNET_new (struct GNUNET_TESTING_PluginFunctions); + api->start_testcase = &start_testcase; + api->get_waiting_for_barriers = get_waiting_for_barriers; + return api; +} + + +/** + * Exit point from the plugin. + * + * @param cls the return value from #libgnunet_test_transport_plugin_simple_send_performance_init + * @return NULL + */ +void * +libgnunet_test_transport_plugin_cmd_simple_send_performance_done (void *cls) +{ + struct GNUNET_TESTING_PluginFunctions *api = cls; + + GNUNET_free (api); + return NULL; +} + + +/* end of plugin_cmd_simple_send.c */ diff --git a/src/transport/test_transport_simple_send_performance.sh b/src/transport/test_transport_simple_send_performance.sh new file mode 100755 index 000000000..12798c2f0 --- /dev/null +++ b/src/transport/test_transport_simple_send_performance.sh @@ -0,0 +1,11 @@ +#!/bin/bash +if ! [ -d "/run/netns" ]; then + echo You have to create the directory /run/netns. +fi +if [ -f /proc/sys/kernel/unprivileged_userns_clone ]; then + if [ "$(cat /proc/sys/kernel/unprivileged_userns_clone)" != 1 ]; then + 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 +fi +exec unshare -r -nmU bash -c "mount -t tmpfs --make-rshared tmpfs /run/netns; ./test_transport_start_with_config test_transport_simple_send_performance_topo.conf" diff --git a/src/transport/test_transport_simple_send_performance_topo.conf b/src/transport/test_transport_simple_send_performance_topo.conf new file mode 100644 index 000000000..1c73952d2 --- /dev/null +++ b/src/transport/test_transport_simple_send_performance_topo.conf @@ -0,0 +1,6 @@ +M:2 +N:1 +X:0 +T:libgnunet_test_transport_plugin_cmd_simple_send_performance +P:1:1|{connect:{P:1:2:tcp}} +P:1:2|{connect:{P:1:1:tcp}} \ No newline at end of file diff --git a/src/transport/transport-testing-cmds.h b/src/transport/transport-testing-cmds.h index 46f6045dc..6e3c761f2 100644 --- a/src/transport/transport-testing-cmds.h +++ b/src/transport/transport-testing-cmds.h @@ -304,6 +304,28 @@ GNUNET_TRANSPORT_cmd_send_simple (const char *label, struct GNUNET_TESTING_NetjailTopology * topology); +/** + * + * + * @param label name for command. + * @param start_peer_label Label of the cmd to start a peer. + * @param create_label Label of the cmd which started the test system. + * @param num Number globally identifying the node. + * @param size The size of the test message to send. + * @param max_send The number of messages to send. + * @param topology The topology for the test setup. + * @return command. + */ +struct GNUNET_TESTING_Command +GNUNET_TRANSPORT_cmd_send_simple_performance (const char *label, + const char *start_peer_label, + const char *create_label, + uint32_t num, + int size, + int max_send, + struct GNUNET_TESTING_NetjailTopology * + topology); + /** * Create command. diff --git a/src/transport/transport-testing2.h b/src/transport/transport-testing2.h index b5db28500..b9e492219 100644 --- a/src/transport/transport-testing2.h +++ b/src/transport/transport-testing2.h @@ -435,6 +435,25 @@ struct GNUNET_TRANSPORT_TESTING_TestMessage */ uint32_t num GNUNET_PACKED; }; + +struct GNUNET_TRANSPORT_TESTING_PerformanceTestMessage +{ + /** + * Type is (usually) #GNUNET_TRANSPORT_TESTING_SIMPLE_PERFORMANCE_MTYPE. + */ + struct GNUNET_MessageHeader header; + + /** + * Time this message was send via transport api. + */ + struct GNUNET_TIME_AbsoluteNBO time_send; + + /** + * Monotonically increasing counter throughout the test. + */ + uint32_t num GNUNET_PACKED; +}; + GNUNET_NETWORK_STRUCT_END @@ -774,6 +793,10 @@ GNUNET_TRANSPORT_TESTING_send ( */ #define GNUNET_TRANSPORT_TESTING_SIMPLE_MTYPE2 12346 +/** + * Message type used by #(). + */ +#define GNUNET_TRANSPORT_TESTING_SIMPLE_PERFORMANCE_MTYPE 12347 /** * Type of the closure argument to pass to diff --git a/src/transport/transport_api_cmd_send_simple_performance.c b/src/transport/transport_api_cmd_send_simple_performance.c new file mode 100644 index 000000000..7e195d9ef --- /dev/null +++ b/src/transport/transport_api_cmd_send_simple_performance.c @@ -0,0 +1,219 @@ +/* + This file is part of GNUnet + Copyright (C) 2021 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 testing_api_cmd_start_peer.c + * @brief cmd to start a peer. + * @author t3sserakt + */ +#include "platform.h" +#include "gnunet_util_lib.h" +#include "gnunet_testing_ng_lib.h" +#include "gnunet_testing_netjail_lib.h" +#include "transport-testing2.h" +#include "transport-testing-cmds.h" + +/** + * Generic logging shortcut + */ +#define LOG(kind, ...) GNUNET_log (kind, __VA_ARGS__) + +/** + * Struct to hold information for callbacks. + * + */ +struct SendSimplePerfState +{ + /** + * Context for our asynchronous completion. + */ + struct GNUNET_TESTING_AsyncContext ac; + + /** + * Label of the cmd to start a peer. + * + */ + const char *start_peer_label; + + /** + * Label of the cmd which started the test system. + * + */ + const char *create_label; + + /** + * The topology we get the connected nodes from. + */ + struct GNUNET_TESTING_NetjailTopology *topology; + + /** + * Size of the message in bytes. + */ + int size; + + /** + * Maximum number of messages per peer. + */ + int max_send; +}; + +struct MQWrapper +{ + /** + * State of the command. + */ + struct SendSimplePerfState *sss; + + /** + * Message queue for a peer. + */ + struct GNUNET_MQ_Handle *mq; + + /** + * Number of messages allready send. + */ + uint32_t num_send; +}; + +/** + * The cleanup function of this cmd frees resources the cmd allocated. + * + */ +static void +send_simple_cleanup (void *cls) +{ + struct SendSimpleState *sss = cls; + + GNUNET_free (sss); +} + + +static void +send_simple_single (void *cls) +{ + struct MQWrapper *mq_wrapper = cls; + struct GNUNET_MQ_Envelope *env; + struct GNUNET_TRANSPORT_TESTING_PerformanceTestMessage *test; + struct GNUNET_TIME_Absolute now; + + now = GNUNET_TIME_absolute_get (); + mq_wrapper->num_send++; + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Sending simple test message with size %llu number %u with mq %p max %llu\n", + mq_wrapper->sss->size, + mq_wrapper->num_send, + mq_wrapper->mq, + mq_wrapper->sss->max_send); + + env = GNUNET_MQ_msg_extra (test, + mq_wrapper->sss->size - sizeof(*test), + GNUNET_TRANSPORT_TESTING_SIMPLE_PERFORMANCE_MTYPE); + test->num = htonl (mq_wrapper->num_send); + test->time_send = GNUNET_TIME_absolute_hton (now); + memset (&test[1], + '1', + mq_wrapper->sss->size - sizeof(*test)); + GNUNET_MQ_send (mq_wrapper->mq, + env); + if (mq_wrapper->sss->max_send > mq_wrapper->num_send) + GNUNET_SCHEDULER_add_now (&send_simple_single, mq_wrapper); + else + GNUNET_TESTING_async_finish (&mq_wrapper->sss->ac); +} + + +static int +send_simple_cb (void *cls, + const struct GNUNET_ShortHashCode *key, + void *value) +{ + struct SendSimplePerfState *sss = cls; + struct GNUNET_MQ_Handle *mq = value; + struct MQWrapper *mq_wrapper = GNUNET_new (struct MQWrapper); + + mq_wrapper->sss = sss; + mq_wrapper->mq = mq; + send_simple_single (mq_wrapper); + + return GNUNET_OK; +} + + +/** + * The run method of this cmd will send a simple message to the connected peers. + * + */ +static void +send_simple_run (void *cls, + struct GNUNET_TESTING_Interpreter *is) +{ + struct SendSimplePerfState *sss = cls; + const struct GNUNET_CONTAINER_MultiShortmap *connected_peers_map; + const struct GNUNET_TESTING_Command *peer1_cmd; + const struct GNUNET_TESTING_Command *system_cmd; + const struct GNUNET_TESTING_System *tl_system; + + + peer1_cmd = GNUNET_TESTING_interpreter_lookup_command (is, + sss->start_peer_label); + GNUNET_TRANSPORT_get_trait_connected_peers_map (peer1_cmd, + &connected_peers_map); + + system_cmd = GNUNET_TESTING_interpreter_lookup_command (is, + sss->create_label); + GNUNET_TESTING_get_trait_test_system (system_cmd, + &tl_system); + + GNUNET_CONTAINER_multishortmap_iterate ( + (struct GNUNET_CONTAINER_MultiShortmap *) + connected_peers_map, send_simple_cb, + sss); +} + + +struct GNUNET_TESTING_Command +GNUNET_TRANSPORT_cmd_send_simple_performance (const char *label, + const char *start_peer_label, + const char *create_label, + uint32_t num, + int size, + int max_send, + struct GNUNET_TESTING_NetjailTopology * + topology) +{ + struct SendSimplePerfState *sss; + struct GNUNET_TESTING_Command cmd; + + sss = GNUNET_new (struct SendSimplePerfState); + sss->start_peer_label = start_peer_label; + sss->create_label = create_label; + sss->topology = topology; + sss->size = size; + sss->max_send = max_send; + + cmd = GNUNET_TESTING_command_new (sss, + label, + &send_simple_run, + &send_simple_cleanup, + NULL, + &sss->ac); + cmd.asynchronous_finish = GNUNET_YES; + return cmd; +} -- cgit v1.2.3