From: Matthias Wachs Date: Wed, 22 Jan 2014 16:22:53 +0000 (+0000) Subject: changes to traffic generation X-Git-Tag: initial-import-from-subversion-38251~4959 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=0c7aa062cb988866f9d859a7c67836707cf1041c;p=oweals%2Fgnunet.git changes to traffic generation --- diff --git a/src/ats-tests/ats-testing.c b/src/ats-tests/ats-testing.c index b93a097d9..8ed1164b3 100644 --- a/src/ats-tests/ats-testing.c +++ b/src/ats-tests/ats-testing.c @@ -26,8 +26,171 @@ */ #include "ats-testing.h" +/** + * Overall state of the performance benchmark + */ +struct BenchmarkState +{ + /** + * Are we connected to ATS service of all peers: GNUNET_YES/NO + */ + int connected_ATS_service; + + /** + * Are we connected to CORE service of all peers: GNUNET_YES/NO + */ + int connected_COMM_service; + + /** + * Are we connected to all peers: GNUNET_YES/NO + */ + int connected_PEERS; + + /** + * Are we connected to all slave peers on CORE level: GNUNET_YES/NO + */ + int connected_CORE; + + /** + * Are we connected to CORE service of all peers: GNUNET_YES/NO + */ + int benchmarking; +}; + + + + +/** + * Connect peers with testbed + */ +struct TestbedConnectOperation +{ + /** + * The benchmarking master initiating this connection + */ + struct BenchmarkPeer *master; + + /** + * The benchmarking slave to connect to + */ + struct BenchmarkPeer *slave; + + /** + * Testbed operation to connect peers + */ + struct GNUNET_TESTBED_Operation *connect_op; +}; + +struct GNUNET_ATS_TEST_Topology +{ + /** + * Shutdown task + */ + GNUNET_SCHEDULER_TaskIdentifier shutdown_task; + + /** + * Progress task + */ + GNUNET_SCHEDULER_TaskIdentifier progress_task; + + /** + * Test result + */ + int result; + + /** + * Test result logging + */ + int logging; + + /**Test core (GNUNET_YES) or transport (GNUNET_NO) + */ + int test_core; + + /** + * Solver string + */ + char *solver; + + /** + * Preference string + */ + char *testname; + + /** + * Preference string + */ + char *pref_str; + + /** + * ATS preference value + */ + int pref_val; + + /** + * Number master peers + */ + unsigned int num_masters; + + /** + * Array of master peers + */ + struct BenchmarkPeer *mps; + + /** + * Number slave peers + */ + unsigned int num_slaves; + + /** + * Array of slave peers + */ + struct BenchmarkPeer *sps; + + /** + * Benchmark duration + */ + struct GNUNET_TIME_Relative perf_duration; + + /** + * Logging frequency + */ + struct GNUNET_TIME_Relative log_frequency; + + /** + * Benchmark state + */ + struct BenchmarkState state; + + struct GNUNET_CORE_MessageHandler *handlers; + + GNUNET_TRANSPORT_ReceiveCallback transport_recv_cb; + + GNUNET_ATS_TESTING_TopologySetupDoneCallback done_cb; + GNUNET_ATS_AddressInformationCallback ats_perf_cb; + void *done_cb_cls; +}; + + + static struct GNUNET_ATS_TEST_Topology *top; +struct TrafficGenerator *tg_head; +struct TrafficGenerator *tg_tail; + +struct TrafficGenerator +{ + struct TrafficGenerator *prev; + struct TrafficGenerator *next; + + struct BenchmarkPeer *src; + struct BenchmarkPartner *dest; + unsigned int rate; + GNUNET_SCHEDULER_Task next_send; + struct GNUNET_TIME_Absolute last_sent; + struct GNUNET_TIME_Relative delta; +}; + /** * Shutdown nicely * @@ -41,6 +204,8 @@ do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) int c_s; int c_op; struct BenchmarkPeer *p; + struct TrafficGenerator *cur; + struct TrafficGenerator *next; if (GNUNET_YES == top->logging) GNUNET_ATS_TEST_logging_stop (); @@ -48,6 +213,14 @@ do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) top->shutdown_task = GNUNET_SCHEDULER_NO_TASK; top->state.benchmarking = GNUNET_NO; + + next = tg_head; + for (cur = next; NULL != cur; cur = next) + { + next = cur->next; + GNUNET_ATS_TEST_generate_traffic_stop(cur); + } + GNUNET_log(GNUNET_ERROR_TYPE_INFO, _("Benchmarking done\n")); for (c_m = 0; c_m < top->num_masters; c_m++) @@ -137,8 +310,9 @@ do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) GNUNET_free(p->partners); p->partners = NULL; } - GNUNET_SCHEDULER_shutdown (); + GNUNET_free (top); + top = NULL; } static struct BenchmarkPartner * @@ -234,6 +408,9 @@ comm_connect_cb (void *cls, const struct GNUNET_PeerIdentity * peer) "All master peers connected all slave peers\n", id, GNUNET_i2s (peer)); top->state.connected_CORE = GNUNET_YES; + /* Notify about setup done */ + if (NULL != top->done_cb) + top->done_cb (top->done_cb_cls, top->mps, top->sps); } } GNUNET_free(id); @@ -297,12 +474,214 @@ core_disconnect_adapter (void *cls, void *op_result) } + +static size_t +send_ping_ready_cb (void *cls, size_t size, void *buf) +{ + struct BenchmarkPartner *p = cls; + static char msgbuf[TEST_MESSAGE_SIZE]; + struct GNUNET_MessageHeader *msg; + + if (NULL == buf) + { + GNUNET_break (0); + return 0; + } + if (size < TEST_MESSAGE_SIZE) + { + GNUNET_break (0); + return 0; + } + + GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Master [%u]: Sending PING to [%u]\n", + p->me->no, p->dest->no); + + if (top->test_core) + { + if (NULL == p->cth) + { + GNUNET_break (0); + } + p->cth = NULL; + } + else + { + if (NULL == p->tth) + { + GNUNET_break (0); + } + p->tth = NULL; + } + + msg = (struct GNUNET_MessageHeader *) &msgbuf; + memset (&msgbuf, 'a', TEST_MESSAGE_SIZE); + msg->type = htons (TEST_MESSAGE_TYPE_PING); + msg->size = htons (TEST_MESSAGE_SIZE); + memcpy (buf, msg, TEST_MESSAGE_SIZE); + + p->messages_sent++; + p->bytes_sent += TEST_MESSAGE_SIZE; + p->me->total_messages_sent++; + p->me->total_bytes_sent += TEST_MESSAGE_SIZE; + + return TEST_MESSAGE_SIZE; +} + + +static void +comm_schedule_send (struct BenchmarkPartner *p) +{ + p->last_message_sent = GNUNET_TIME_absolute_get(); + if (GNUNET_YES == top->test_core) + { + p->cth = GNUNET_CORE_notify_transmit_ready ( + p->me->ch, GNUNET_NO, 0, GNUNET_TIME_UNIT_MINUTES, &p->dest->id, + TEST_MESSAGE_SIZE, &send_ping_ready_cb, p); + } + else + { + p->tth = GNUNET_TRANSPORT_notify_transmit_ready ( + p->me->th, &p->dest->id, TEST_MESSAGE_SIZE, 0,GNUNET_TIME_UNIT_MINUTES, + &send_ping_ready_cb, p); + } +} + +static struct TrafficGenerator * +find_tg (struct BenchmarkPartner *p) +{ + struct TrafficGenerator *cur; + for (cur = tg_head; NULL != cur; cur = cur->next) + if ( (0 == memcmp (&p->me->id, &cur->dest->me, sizeof (cur->dest->me))) && + (0 == memcmp (&p->dest->id, &cur->dest->dest->id, sizeof (cur->dest->dest->id))) ) + return cur; + + return NULL; +} + +static int +core_handle_pong (void *cls, const struct GNUNET_PeerIdentity *other, + const struct GNUNET_MessageHeader *message) +{ + struct BenchmarkPeer *me = cls; + struct BenchmarkPartner *p = NULL; + struct TrafficGenerator *tg; + + if (NULL == (p = find_partner (me, other))) + { + GNUNET_break(0); + return GNUNET_SYSERR; + } + + GNUNET_log(GNUNET_ERROR_TYPE_ERROR, + "Master [%u]: Received PONG from [%u], next message\n", me->no, + p->dest->no); + + p->messages_received++; + p->bytes_received += TEST_MESSAGE_SIZE; + p->me->total_messages_received++; + p->me->total_bytes_received += TEST_MESSAGE_SIZE; + p->total_app_rtt += GNUNET_TIME_absolute_get_difference(p->last_message_sent, + GNUNET_TIME_absolute_get()).rel_value_us; + + + tg = find_tg(p); +/* + if (GNUNET_TIME_absolute_max(GNUNET_TIME_absolute_get(), tg->next_send))*/ + comm_schedule_send (p); + return GNUNET_OK; +} + +static size_t +comm_send_pong_ready (void *cls, size_t size, void *buf) +{ + static char msgbuf[TEST_MESSAGE_SIZE]; + struct BenchmarkPartner *p = cls; + struct GNUNET_MessageHeader *msg; + + if (GNUNET_YES == top->test_core) + p->cth = NULL; + else + p->tth = NULL; + + p->messages_sent++; + p->bytes_sent += TEST_MESSAGE_SIZE; + p->me->total_messages_sent++; + p->me->total_bytes_sent += TEST_MESSAGE_SIZE; + + msg = (struct GNUNET_MessageHeader *) &msgbuf; + memset (&msgbuf, 'a', TEST_MESSAGE_SIZE); + msg->type = htons (TEST_MESSAGE_TYPE_PONG); + msg->size = htons (TEST_MESSAGE_SIZE); + memcpy (buf, msg, TEST_MESSAGE_SIZE); + + return TEST_MESSAGE_SIZE; +} + + +static int +core_handle_ping (void *cls, const struct GNUNET_PeerIdentity *other, + const struct GNUNET_MessageHeader *message) +{ + struct BenchmarkPeer *me = cls; + struct BenchmarkPartner *p = NULL; + + if (NULL == (p = find_partner(me, other))) + { + GNUNET_break(0); + return GNUNET_SYSERR; + } + + GNUNET_log(GNUNET_ERROR_TYPE_ERROR, + "Slave [%u]: Received PING from [%u], sending PONG\n", me->no, + p->dest->no); + + p->messages_received++; + p->bytes_received += TEST_MESSAGE_SIZE; + p->me->total_messages_received++; + p->me->total_bytes_received += TEST_MESSAGE_SIZE; + + if (GNUNET_YES == top->test_core) + { + GNUNET_assert (NULL == p->cth); + + p->cth = GNUNET_CORE_notify_transmit_ready (me->ch, GNUNET_NO, 0, + GNUNET_TIME_UNIT_MINUTES, &p->dest->id, TEST_MESSAGE_SIZE, + &comm_send_pong_ready, p); + } + else + { + GNUNET_assert (NULL == p->tth); + p->tth = GNUNET_TRANSPORT_notify_transmit_ready (me->th, &p->dest->id, + TEST_MESSAGE_SIZE, 0, GNUNET_TIME_UNIT_MINUTES, &comm_send_pong_ready, + p); + } + return GNUNET_OK; +} + +static void +test_recv_cb (void *cls, + const struct GNUNET_PeerIdentity * peer, + const struct GNUNET_MessageHeader * message) +{ + if (TEST_MESSAGE_SIZE != ntohs (message->size) || + (TEST_MESSAGE_TYPE_PING != ntohs (message->type) && + TEST_MESSAGE_TYPE_PONG != ntohs (message->type))) + { + return; + } + if (TEST_MESSAGE_TYPE_PING == ntohs (message->type)) + core_handle_ping (cls, peer, message); + if (TEST_MESSAGE_TYPE_PONG == ntohs (message->type)) + core_handle_pong (cls, peer, message); +} + + static void * transport_connect_adapter (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg) { struct BenchmarkPeer *me = cls; - me->th = GNUNET_TRANSPORT_connect (cfg, &me->id, me, top->transport_recv_cb, + me->th = GNUNET_TRANSPORT_connect (cfg, &me->id, me, &test_recv_cb, &comm_connect_cb, &comm_disconnect_cb); if (NULL == me->th) GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to create transport connection \n"); @@ -352,9 +731,6 @@ connect_completion_callback (void *cls, struct GNUNET_TESTBED_Operation *op, if (ops == top->num_masters * top->num_slaves) { top->state.connected_PEERS = GNUNET_YES; - /* Notify about setup done */ - if (NULL != top->done_cb) - top->done_cb (top->done_cb_cls, top->mps, top->sps); } } @@ -463,6 +839,101 @@ do_comm_connect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) } } +static void +ats_performance_info_cb (void *cls, const struct GNUNET_HELLO_Address *address, + int address_active, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out, + struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, + const struct GNUNET_ATS_Information *ats, uint32_t ats_count) +{ + struct BenchmarkPeer *me = cls; + struct BenchmarkPartner *p; + int c_a; + int log; + char *peer_id; + + p = find_partner (me, &address->peer); + if (NULL == p) + { + /* This is not one of my partners + * Will happen since the peers will connect to each other due to gossiping + */ + return; + } + peer_id = GNUNET_strdup (GNUNET_i2s (&me->id)); + + log = GNUNET_NO; + if ((p->bandwidth_in != ntohl (bandwidth_in.value__)) || + (p->bandwidth_out != ntohl (bandwidth_out.value__))) + log = GNUNET_YES; + p->bandwidth_in = ntohl (bandwidth_in.value__); + p->bandwidth_out = ntohl (bandwidth_out.value__); + + for (c_a = 0; c_a < ats_count; c_a++) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%s [%u] received ATS information: %s %s %u\n", + (GNUNET_YES == p->me->master) ? "Master" : "Slave", + p->me->no, + GNUNET_i2s (&p->dest->id), + GNUNET_ATS_print_property_type(ntohl(ats[c_a].type)), + ntohl(ats[c_a].value)); + switch (ntohl (ats[c_a].type )) + { + case GNUNET_ATS_ARRAY_TERMINATOR: + break; + case GNUNET_ATS_UTILIZATION_OUT: + if (p->ats_utilization_up != ntohl (ats[c_a].value)) + log = GNUNET_YES; + p->ats_utilization_up = ntohl (ats[c_a].value); + + break; + case GNUNET_ATS_UTILIZATION_IN: + if (p->ats_utilization_down != ntohl (ats[c_a].value)) + log = GNUNET_YES; + p->ats_utilization_down = ntohl (ats[c_a].value); + break; + case GNUNET_ATS_NETWORK_TYPE: + if (p->ats_network_type != ntohl (ats[c_a].value)) + log = GNUNET_YES; + p->ats_network_type = ntohl (ats[c_a].value); + break; + case GNUNET_ATS_QUALITY_NET_DELAY: + if (p->ats_delay != ntohl (ats[c_a].value)) + log = GNUNET_YES; + p->ats_delay = ntohl (ats[c_a].value); + break; + case GNUNET_ATS_QUALITY_NET_DISTANCE: + if (p->ats_distance != ntohl (ats[c_a].value)) + log = GNUNET_YES; + p->ats_distance = ntohl (ats[c_a].value); + GNUNET_break (0); + break; + case GNUNET_ATS_COST_WAN: + if (p->ats_cost_wan != ntohl (ats[c_a].value)) + log = GNUNET_YES; + p->ats_cost_wan = ntohl (ats[c_a].value); + break; + case GNUNET_ATS_COST_LAN: + if (p->ats_cost_lan != ntohl (ats[c_a].value)) + log = GNUNET_YES; + p->ats_cost_lan = ntohl (ats[c_a].value); + break; + case GNUNET_ATS_COST_WLAN: + if (p->ats_cost_wlan != ntohl (ats[c_a].value)) + log = GNUNET_YES; + p->ats_cost_wlan = ntohl (ats[c_a].value); + break; + default: + break; + } + } + if ((GNUNET_YES == top->logging) && (GNUNET_YES == log)) + GNUNET_ATS_TEST_logging_now(); + + top->ats_perf_cb (cls, address, address_active, bandwidth_out, bandwidth_in, + ats, ats_count); + GNUNET_free(peer_id); +} + static void * ats_perf_connect_adapter (void *cls, @@ -470,7 +941,7 @@ ats_perf_connect_adapter (void *cls, { struct BenchmarkPeer *me = cls; - me->ats_perf_handle = GNUNET_ATS_performance_init (cfg, top->ats_perf_cb, me); + me->ats_perf_handle = GNUNET_ATS_performance_init (cfg, ats_performance_info_cb, me); if (NULL == me->ats_perf_handle) GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to create ATS performance handle \n"); @@ -662,6 +1133,7 @@ controller_event_cb (void *cls, } } + void GNUNET_ATS_TEST_create_topology (char *name, char *cfg_file, unsigned int num_slaves, @@ -669,11 +1141,15 @@ GNUNET_ATS_TEST_create_topology (char *name, char *cfg_file, int test_core, GNUNET_ATS_TESTING_TopologySetupDoneCallback done_cb, void *done_cb_cls, - struct GNUNET_CORE_MessageHandler *handlers, GNUNET_TRANSPORT_ReceiveCallback transport_recv_cb, GNUNET_ATS_AddressInformationCallback ats_perf_cb) { + static struct GNUNET_CORE_MessageHandler handlers[] = { + {&core_handle_ping, TEST_MESSAGE_TYPE_PING, 0 }, + {&core_handle_pong, TEST_MESSAGE_TYPE_PONG, 0 }, + { NULL, 0, 0 } }; + top = GNUNET_new (struct GNUNET_ATS_TEST_Topology); top->num_masters = num_masters; top->num_slaves = num_slaves; @@ -700,7 +1176,83 @@ GNUNET_ATS_TEST_create_topology (char *name, char *cfg_file, void GNUNET_ATS_TEST_shutdown_topology (void) { + if (NULL == top) + return; + GNUNET_SCHEDULER_shutdown(); } + + +struct TrafficGenerator * +GNUNET_ATS_TEST_generate_traffic_start (struct BenchmarkPeer *src, + struct BenchmarkPartner *dest, unsigned int rate, + struct GNUNET_TIME_Relative duration) +{ + struct TrafficGenerator * tg; + tg = NULL; + + tg = GNUNET_new (struct TrafficGenerator); + GNUNET_CONTAINER_DLL_insert (tg_head, tg_tail, tg); + tg->src = src; + tg->dest = dest; + tg->rate = rate; + + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Setting up traffic generator between master[%u] `%s' and slave [%u] `%s' sending with %u Bytes/sec\n", + dest->me->no, GNUNET_i2s (&dest->me->id), + dest->dest->no, GNUNET_i2s (&dest->dest->id), + rate); + + if (top->test_core) + { + if (NULL != dest->cth) + { + GNUNET_break (0); + return tg; + } + dest->cth = GNUNET_CORE_notify_transmit_ready (src->ch, GNUNET_NO, + UINT32_MAX, GNUNET_TIME_UNIT_FOREVER_REL, &dest->dest->id, + TEST_MESSAGE_SIZE, &send_ping_ready_cb, dest); + } + else + { + if (NULL != dest->tth) + { + GNUNET_break (0); + return tg; + } + dest->tth = GNUNET_TRANSPORT_notify_transmit_ready (src->th, &dest->dest->id, + TEST_MESSAGE_SIZE, UINT32_MAX, GNUNET_TIME_UNIT_FOREVER_REL, + &send_ping_ready_cb, dest); + tg->last_sent = GNUNET_TIME_absolute_get(); + tg->delta.rel_value_us = (GNUNET_TIME_UNIT_SECONDS.rel_value_us / (rate / TEST_MESSAGE_SIZE)); + } + return tg; +} + +void +GNUNET_ATS_TEST_generate_traffic_stop (struct TrafficGenerator *tg) +{ + GNUNET_CONTAINER_DLL_remove (tg_head, tg_tail, tg); + + if (top->test_core) + { + if (NULL != tg->dest->cth) + { + GNUNET_CORE_notify_transmit_ready_cancel (tg->dest->cth); + tg->dest->cth = NULL; + } + } + else + { + if (NULL != tg->dest->tth) + { + GNUNET_TRANSPORT_notify_transmit_ready_cancel (tg->dest->tth); + tg->dest->tth = NULL; + } + } + GNUNET_free (tg); +} + /* end of file ats-testing.c */ diff --git a/src/ats-tests/ats-testing.h b/src/ats-tests/ats-testing.h index 540f2bd8c..a3d208187 100644 --- a/src/ats-tests/ats-testing.h +++ b/src/ats-tests/ats-testing.h @@ -31,116 +31,18 @@ #define TEST_ATS_PREFERENCE_DEFAULT 1.0 -/** - * Overall state of the performance benchmark - */ -struct BenchmarkState -{ - /** - * Are we connected to ATS service of all peers: GNUNET_YES/NO - */ - int connected_ATS_service; - - /** - * Are we connected to CORE service of all peers: GNUNET_YES/NO - */ - int connected_COMM_service; - - /** - * Are we connected to all peers: GNUNET_YES/NO - */ - int connected_PEERS; +#define TEST_MESSAGE_TYPE_PING 12345 +#define TEST_MESSAGE_TYPE_PONG 12346 +#define TEST_MESSAGE_SIZE 1000 - /** - * Are we connected to all slave peers on CORE level: GNUNET_YES/NO - */ - int connected_CORE; - - /** - * Are we connected to CORE service of all peers: GNUNET_YES/NO - */ - int benchmarking; -}; - - -/** - * Information about a benchmarking partner - */ -struct BenchmarkPartner -{ - /** - * The peer itself this partner belongs to - */ - struct BenchmarkPeer *me; - - /** - * The partner peer - */ - struct BenchmarkPeer *dest; - - /** - * Core transmit handles - */ - struct GNUNET_CORE_TransmitHandle *cth; - - /** - * Transport transmit handles - */ - struct GNUNET_TRANSPORT_TransmitHandle *tth; - - /** - * Timestamp to calculate communication layer delay - */ - struct GNUNET_TIME_Absolute last_message_sent; - - /** - * Accumulated RTT for all messages - */ - unsigned int total_app_rtt; - - /** - * Number of messages sent to this partner - */ - unsigned int messages_sent; - - /** - * Number of bytes sent to this partner - */ - unsigned int bytes_sent; - - /** - * Number of messages received from this partner - */ - unsigned int messages_received; - - /** - * Number of bytes received from this partner - */ - unsigned int bytes_received; - - /* Current ATS properties */ - - uint32_t ats_distance; - - uint32_t ats_delay; - - uint32_t bandwidth_in; - - uint32_t bandwidth_out; - - uint32_t ats_utilization_up; - - uint32_t ats_utilization_down; - - uint32_t ats_network_type; - - uint32_t ats_cost_wan; - - uint32_t ats_cost_lan; - - uint32_t ats_cost_wlan; -}; +struct BenchmarkPartner; +struct BenchmarkPeer; +struct GNUNET_ATS_TEST_Topology; +struct TrafficGenerator; +typedef void (*GNUNET_ATS_TESTING_TopologySetupDoneCallback) (void *cls, + struct BenchmarkPeer *masters, + struct BenchmarkPeer *slaves); /** * Information we track for a peer in the testbed. @@ -264,121 +166,93 @@ struct BenchmarkPeer unsigned int total_bytes_received; }; + /** - * Connect peers with testbed + * Information about a benchmarking partner */ -struct TestbedConnectOperation +struct BenchmarkPartner { /** - * The benchmarking master initiating this connection + * The peer itself this partner belongs to */ - struct BenchmarkPeer *master; + struct BenchmarkPeer *me; /** - * The benchmarking slave to connect to + * The partner peer */ - struct BenchmarkPeer *slave; + struct BenchmarkPeer *dest; /** - * Testbed operation to connect peers + * Core transmit handles */ - struct GNUNET_TESTBED_Operation *connect_op; -}; - -typedef void (*GNUNET_ATS_TESTING_TopologySetupDoneCallback) (void *cls, - struct BenchmarkPeer *masters, - struct BenchmarkPeer *slaves); + struct GNUNET_CORE_TransmitHandle *cth; -struct GNUNET_ATS_TEST_Topology -{ /** - * Shutdown task + * Transport transmit handles */ - GNUNET_SCHEDULER_TaskIdentifier shutdown_task; + struct GNUNET_TRANSPORT_TransmitHandle *tth; /** - * Progress task + * Timestamp to calculate communication layer delay */ - GNUNET_SCHEDULER_TaskIdentifier progress_task; + struct GNUNET_TIME_Absolute last_message_sent; /** - * Test result + * Accumulated RTT for all messages */ - int result; + unsigned int total_app_rtt; /** - * Test result logging - */ - int logging; - - /**Test core (GNUNET_YES) or transport (GNUNET_NO) + * Number of messages sent to this partner */ - int test_core; + unsigned int messages_sent; /** - * Solver string + * Number of bytes sent to this partner */ - char *solver; + unsigned int bytes_sent; /** - * Preference string + * Number of messages received from this partner */ - char *testname; + unsigned int messages_received; /** - * Preference string + * Number of bytes received from this partner */ - char *pref_str; + unsigned int bytes_received; - /** - * ATS preference value - */ - int pref_val; + /* Current ATS properties */ - /** - * Number master peers - */ - unsigned int num_masters; + uint32_t ats_distance; - /** - * Array of master peers - */ - struct BenchmarkPeer *mps; + uint32_t ats_delay; - /** - * Number slave peers - */ - unsigned int num_slaves; + uint32_t bandwidth_in; - /** - * Array of slave peers - */ - struct BenchmarkPeer *sps; + uint32_t bandwidth_out; - /** - * Benchmark duration - */ - struct GNUNET_TIME_Relative perf_duration; + uint32_t ats_utilization_up; - /** - * Logging frequency - */ - struct GNUNET_TIME_Relative log_frequency; + uint32_t ats_utilization_down; - /** - * Benchmark state - */ - struct BenchmarkState state; + uint32_t ats_network_type; - struct GNUNET_CORE_MessageHandler *handlers; + uint32_t ats_cost_wan; - GNUNET_TRANSPORT_ReceiveCallback transport_recv_cb; + uint32_t ats_cost_lan; - GNUNET_ATS_TESTING_TopologySetupDoneCallback done_cb; - GNUNET_ATS_AddressInformationCallback ats_perf_cb; - void *done_cb_cls; + uint32_t ats_cost_wlan; }; +struct TrafficGenerator * +GNUNET_ATS_TEST_generate_traffic_start (struct BenchmarkPeer *src, + struct BenchmarkPartner *dest, unsigned int rate, + struct GNUNET_TIME_Relative duration); + +void +GNUNET_ATS_TEST_generate_traffic_stop (struct TrafficGenerator *tg); + void GNUNET_ATS_TEST_logging_start (struct GNUNET_TIME_Relative log_frequency, char * testname, struct BenchmarkPeer *masters, int num_masters); @@ -396,7 +270,6 @@ GNUNET_ATS_TEST_create_topology (char *name, char *cfg_file, int test_core, GNUNET_ATS_TESTING_TopologySetupDoneCallback done_cb, void *done_cb_cls, - struct GNUNET_CORE_MessageHandler *handlers, GNUNET_TRANSPORT_ReceiveCallback transport_recv_cb, GNUNET_ATS_AddressInformationCallback ats_perf_cb); diff --git a/src/ats-tests/gnunet-ats-sim.c b/src/ats-tests/gnunet-ats-sim.c index b394cb8a4..993a8a0e4 100644 --- a/src/ats-tests/gnunet-ats-sim.c +++ b/src/ats-tests/gnunet-ats-sim.c @@ -35,8 +35,13 @@ #define DEFAULT_NUM_SLAVES 5 #define DEFAULT_NUM_MASTERS 1 +#define TEST_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10) + #define TEST_MESSAGE_TYPE_PING 12345 -#define TEST_MESSAGE_TYPE_PONG 12346 +#define TEST_MESSAGE_TYPE_PONG 1234 + +static struct BenchmarkPeer *masters_p; +static struct BenchmarkPeer *slaves_p; /** * Number of master peers to use @@ -48,18 +53,74 @@ static int c_masters; */ static int c_slaves; -static int -core_handle_pong (void *cls, const struct GNUNET_PeerIdentity *other, - const struct GNUNET_MessageHeader *message) +static void +evaluate () { - return 0; + int c_m; + int c_s; + unsigned int duration; + struct BenchmarkPeer *mp; + struct BenchmarkPartner *p; + + unsigned int kb_sent_sec; + double kb_sent_percent; + unsigned int kb_recv_sec; + double kb_recv_percent; + unsigned int rtt; + + duration = (TEST_TIMEOUT.rel_value_us / (1000 * 1000)); + for (c_m = 0; c_m < c_masters; c_m++) + { + mp = &masters_p[c_m]; + fprintf (stderr, + _("Master [%u]: sent: %u KiB in %u sec. = %u KiB/s, received: %u KiB in %u sec. = %u KiB/s\n"), + mp->no, mp->total_bytes_sent / 1024, duration, + (mp->total_bytes_sent / 1024) / duration, + mp->total_bytes_received / 1024, duration, + (mp->total_bytes_received / 1024) / duration); + + for (c_s = 0; c_s < c_slaves; c_s++) + { + p = &mp->partners[c_s]; + + kb_sent_sec = 0; + kb_recv_sec = 0; + kb_sent_percent = 0.0; + kb_recv_percent = 0.0; + rtt = 0; + + if (duration > 0) + { + kb_sent_sec = (p->bytes_sent / 1024) / duration; + kb_recv_sec = (p->bytes_received / 1024) / duration; + } + + if (mp->total_bytes_sent > 0) + kb_sent_percent = ((double) p->bytes_sent * 100) / mp->total_bytes_sent; + if (mp->total_bytes_received > 0) + kb_recv_percent = ((double) p->bytes_received * 100) / mp->total_bytes_received; + if (1000 * p->messages_sent > 0) + rtt = p->total_app_rtt / (1000 * p->messages_sent); + fprintf (stderr, + "%c Master [%u] -> Slave [%u]: sent %u KiB/s (%.2f %%), received %u KiB/s (%.2f %%)\n", + (mp->pref_partner == p->dest) ? '*' : ' ', + mp->no, p->dest->no, + kb_sent_sec, kb_sent_percent, + kb_recv_sec, kb_recv_percent); + fprintf (stderr, + "%c Master [%u] -> Slave [%u]: Average application layer RTT: %u ms\n", + (mp->pref_partner == p->dest) ? '*' : ' ', + mp->no, p->dest->no, rtt); + } + } } -static int -core_handle_ping (void *cls, const struct GNUNET_PeerIdentity *other, - const struct GNUNET_MessageHeader *message) +static void +do_shutdown () { - return 0; + /* Shutdown a topology with */ + evaluate (); + GNUNET_ATS_TEST_shutdown_topology (); } static void @@ -83,21 +144,30 @@ static void topology_setup_done (void *cls, struct BenchmarkPeer *masters, struct BenchmarkPeer *slaves) { + int c_m; + int c_s; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Topology setup complete!\n"); - - /* Shutdown a topology with */ - GNUNET_ATS_TEST_shutdown_topology (); + masters_p = masters; + slaves_p = slaves; + + for (c_m = 0; c_m < c_masters; c_m++) + { + for (c_s = 0; c_s < c_slaves; c_s++) + { + /* Generate maximum traffic to all peers */ + GNUNET_ATS_TEST_generate_traffic_start (&masters[c_m], + &masters[c_m].partners[c_s], 10000, + GNUNET_TIME_UNIT_FOREVER_REL); + } + } + GNUNET_SCHEDULER_add_delayed (TEST_TIMEOUT, &do_shutdown, NULL); } + int main (int argc, char *argv[]) { - static struct GNUNET_CORE_MessageHandler handlers[] = { - {&core_handle_ping, TEST_MESSAGE_TYPE_PING, 0 }, - {&core_handle_pong, TEST_MESSAGE_TYPE_PONG, 0 }, - { NULL, 0, 0 } }; - c_slaves = DEFAULT_NUM_SLAVES; c_masters = DEFAULT_NUM_MASTERS; @@ -105,10 +175,9 @@ main (int argc, char *argv[]) GNUNET_ATS_TEST_create_topology ("gnunet-ats-sim", "perf_ats_proportional_none.conf", c_slaves, c_masters, - GNUNET_YES, + GNUNET_NO, &topology_setup_done, NULL, - handlers, &transport_recv_cb, &ats_performance_info_cb); return 0; diff --git a/src/ats-tests/perf_ats.c b/src/ats-tests/perf_ats.c index 9d56ab659..08b6a1518 100644 --- a/src/ats-tests/perf_ats.c +++ b/src/ats-tests/perf_ats.c @@ -35,9 +35,6 @@ #define TEST_ATS_PREFRENCE_START 1.0 #define TEST_ATS_PREFRENCE_DELTA 1.0 -#define TEST_MESSAGE_TYPE_PING 12345 -#define TEST_MESSAGE_TYPE_PONG 12346 -#define TEST_MESSAGE_SIZE 1000 #define TEST_MESSAGE_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1) #define TEST_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 120) @@ -150,9 +147,6 @@ evaluate () { p = &mp->partners[c_s]; - fprintf (stderr , "%u %u %u\n", p->bytes_sent, (p->bytes_sent / 1024) / duration, duration); - fprintf (stderr , "%u %u %u \n", p->bytes_received, (p->bytes_sent / 1024) / duration, duration); - kb_sent_sec = 0; kb_recv_sec = 0; kb_sent_percent = 0.0; @@ -171,16 +165,12 @@ evaluate () kb_recv_percent = ((double) p->bytes_received * 100) / mp->total_bytes_received; if (1000 * p->messages_sent > 0) rtt = p->total_app_rtt / (1000 * p->messages_sent); - - - fprintf (stderr, "%c Master [%u] -> Slave [%u]: sent %u KiB/s (%.2f %%), received %u KiB/s (%.2f %%)\n", (mp->pref_partner == p->dest) ? '*' : ' ', mp->no, p->dest->no, kb_sent_sec, kb_sent_percent, kb_recv_sec, kb_recv_percent); - fprintf (stderr, "%c Master [%u] -> Slave [%u]: Average application layer RTT: %u ms\n", (mp->pref_partner == p->dest) ? '*' : ' ', @@ -216,63 +206,6 @@ do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) GNUNET_ATS_TEST_shutdown_topology(); } -static size_t -comm_send_ready (void *cls, size_t size, void *buf) -{ - static char msgbuf[TEST_MESSAGE_SIZE]; - struct BenchmarkPartner *p = cls; - struct GNUNET_MessageHeader *msg; - - if (GNUNET_YES == test_core) - p->cth = NULL; - else - p->tth = NULL; - - if (NULL == buf) - { - GNUNET_break (0); - return 0; - } - if (size < TEST_MESSAGE_SIZE) - { - GNUNET_break (0); - return 0; - } - - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Master [%u]: Sending PING to [%u]\n", - p->me->no, p->dest->no); - - p->messages_sent++; - p->bytes_sent += TEST_MESSAGE_SIZE; - p->me->total_messages_sent++; - p->me->total_bytes_sent += TEST_MESSAGE_SIZE; - - msg = (struct GNUNET_MessageHeader *) &msgbuf; - memset (&msgbuf, 'a', TEST_MESSAGE_SIZE); - msg->type = htons (TEST_MESSAGE_TYPE_PING); - msg->size = htons (TEST_MESSAGE_SIZE); - memcpy (buf, msg, TEST_MESSAGE_SIZE); - return TEST_MESSAGE_SIZE; -} - -static void -comm_schedule_send (struct BenchmarkPartner *p) -{ - p->last_message_sent = GNUNET_TIME_absolute_get(); - if (GNUNET_YES == test_core) - { - p->cth = GNUNET_CORE_notify_transmit_ready ( - p->me->ch, GNUNET_NO, 0, GNUNET_TIME_UNIT_MINUTES, &p->dest->id, - TEST_MESSAGE_SIZE, &comm_send_ready, p); - } - else - { - p->tth = GNUNET_TRANSPORT_notify_transmit_ready ( - p->me->th, &p->dest->id, TEST_MESSAGE_SIZE, 0,GNUNET_TIME_UNIT_MINUTES, - &comm_send_ready, p); - } - -} static void print_progress () @@ -306,64 +239,50 @@ ats_pref_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) } static void -do_benchmark (void *cls, struct BenchmarkPeer *masters, struct BenchmarkPeer *slaves) +start_benchmark() { int c_m; int c_s; - mps = masters; - sps = slaves; - GNUNET_log(GNUNET_ERROR_TYPE_INFO, _("Benchmarking start\n")); if (GNUNET_SCHEDULER_NO_TASK != shutdown_task) - GNUNET_SCHEDULER_cancel (shutdown_task); - shutdown_task = GNUNET_SCHEDULER_add_delayed (perf_duration, - &do_shutdown, NULL ); + GNUNET_SCHEDULER_cancel(shutdown_task); + shutdown_task = GNUNET_SCHEDULER_add_delayed(perf_duration, &do_shutdown, + NULL ); - progress_task = GNUNET_SCHEDULER_add_now (&print_progress, NULL ); + progress_task = GNUNET_SCHEDULER_add_now(&print_progress, NULL ); - GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Topology connected, start benchmarking...\n"); + GNUNET_log(GNUNET_ERROR_TYPE_INFO, + "Topology connected, start benchmarking...\n"); /* Start sending test messages */ for (c_m = 0; c_m < num_masters; c_m++) - { - for (c_s = 0; c_s < num_slaves; c_s++) - comm_schedule_send (&masters[c_m].partners[c_s]); - if (pref_val != GNUNET_ATS_PREFERENCE_END) - masters[c_m].ats_task = GNUNET_SCHEDULER_add_now (&ats_pref_task, &masters[c_m]); - } + { + for (c_s = 0; c_s < num_slaves; c_s++) + { + GNUNET_ATS_TEST_generate_traffic_start (&mps[c_m], &mps[c_m].partners[c_s], + UINT32_MAX, GNUNET_TIME_UNIT_FOREVER_REL); + } + if (pref_val != GNUNET_ATS_PREFERENCE_END) + mps[c_m].ats_task = GNUNET_SCHEDULER_add_now(&ats_pref_task, &mps[c_m]); + } if (GNUNET_YES == logging) - GNUNET_ATS_TEST_logging_start (log_frequency, testname, mps, num_masters); + GNUNET_ATS_TEST_logging_start(log_frequency, testname, mps, num_masters); } - -static size_t -comm_send_pong_ready (void *cls, size_t size, void *buf) +static void +do_benchmark (void *cls, struct BenchmarkPeer *masters, struct BenchmarkPeer *slaves) { - static char msgbuf[TEST_MESSAGE_SIZE]; - struct BenchmarkPartner *p = cls; - struct GNUNET_MessageHeader *msg; + mps = masters; + sps = slaves; - if (GNUNET_YES == test_core) - p->cth = NULL; - else - p->tth = NULL; + GNUNET_SCHEDULER_add_now(&start_benchmark, NULL); +} - p->messages_sent++; - p->bytes_sent += TEST_MESSAGE_SIZE; - p->me->total_messages_sent++; - p->me->total_bytes_sent += TEST_MESSAGE_SIZE; - msg = (struct GNUNET_MessageHeader *) &msgbuf; - memset (&msgbuf, 'a', TEST_MESSAGE_SIZE); - msg->type = htons (TEST_MESSAGE_TYPE_PONG); - msg->size = htons (TEST_MESSAGE_SIZE); - memcpy (buf, msg, TEST_MESSAGE_SIZE); - return TEST_MESSAGE_SIZE; -} static struct BenchmarkPartner * find_partner (struct BenchmarkPeer *me, const struct GNUNET_PeerIdentity * peer) @@ -384,91 +303,12 @@ find_partner (struct BenchmarkPeer *me, const struct GNUNET_PeerIdentity * peer) return NULL; } -static int -comm_handle_ping (void *cls, const struct GNUNET_PeerIdentity *other, - const struct GNUNET_MessageHeader *message) -{ - - struct BenchmarkPeer *me = cls; - struct BenchmarkPartner *p = NULL; - - if (NULL == (p = find_partner(me, other))) - { - GNUNET_break(0); - return GNUNET_SYSERR; - } - - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "Slave [%u]: Received PING from [%u], sending PONG\n", me->no, - p->dest->no); - - p->messages_received++; - p->bytes_received += TEST_MESSAGE_SIZE; - p->me->total_messages_received++; - p->me->total_bytes_received += TEST_MESSAGE_SIZE; - - if (GNUNET_YES == test_core) - { - GNUNET_assert (NULL == p->cth); - p->cth = GNUNET_CORE_notify_transmit_ready (me->ch, GNUNET_NO, 0, - GNUNET_TIME_UNIT_MINUTES, &p->dest->id, TEST_MESSAGE_SIZE, - &comm_send_pong_ready, p); - } - else - { - GNUNET_assert (NULL == p->tth); - p->tth = GNUNET_TRANSPORT_notify_transmit_ready (me->th, &p->dest->id, - TEST_MESSAGE_SIZE, 0, GNUNET_TIME_UNIT_MINUTES, &comm_send_pong_ready, - p); - } - return GNUNET_OK; -} - -static int -comm_handle_pong (void *cls, const struct GNUNET_PeerIdentity *other, - const struct GNUNET_MessageHeader *message) -{ - struct BenchmarkPeer *me = cls; - struct BenchmarkPartner *p = NULL; - - if (NULL == (p = find_partner (me, other))) - { - GNUNET_break(0); - return GNUNET_SYSERR; - } - - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "Master [%u]: Received PONG from [%u], next message\n", me->no, - p->dest->no); - - p->messages_received++; - p->bytes_received += TEST_MESSAGE_SIZE; - p->me->total_messages_received++; - p->me->total_bytes_received += TEST_MESSAGE_SIZE; - p->total_app_rtt += GNUNET_TIME_absolute_get_difference(p->last_message_sent, - GNUNET_TIME_absolute_get()).rel_value_us; - - comm_schedule_send (p); - return GNUNET_OK; -} - - static void test_recv_cb (void *cls, const struct GNUNET_PeerIdentity * peer, const struct GNUNET_MessageHeader * message) { - if (TEST_MESSAGE_SIZE != ntohs (message->size) || - (TEST_MESSAGE_TYPE_PING != ntohs (message->type) && - TEST_MESSAGE_TYPE_PONG != ntohs (message->type))) - { - return; - } - if (TEST_MESSAGE_TYPE_PING == ntohs (message->type)) - comm_handle_ping (cls, peer, message); - if (TEST_MESSAGE_TYPE_PONG == ntohs (message->type)) - comm_handle_pong (cls, peer, message); } @@ -509,61 +349,9 @@ ats_performance_info_cb (void *cls, const struct GNUNET_HELLO_Address *address, GNUNET_i2s (&p->dest->id), GNUNET_ATS_print_property_type(ntohl(ats[c_a].type)), ntohl(ats[c_a].value)); - switch (ntohl (ats[c_a].type )) - { - case GNUNET_ATS_ARRAY_TERMINATOR: - break; - case GNUNET_ATS_UTILIZATION_OUT: - if (p->ats_utilization_up != ntohl (ats[c_a].value)) - log = GNUNET_YES; - p->ats_utilization_up = ntohl (ats[c_a].value); - - break; - case GNUNET_ATS_UTILIZATION_IN: - if (p->ats_utilization_down != ntohl (ats[c_a].value)) - log = GNUNET_YES; - p->ats_utilization_down = ntohl (ats[c_a].value); - break; - case GNUNET_ATS_NETWORK_TYPE: - if (p->ats_network_type != ntohl (ats[c_a].value)) - log = GNUNET_YES; - p->ats_network_type = ntohl (ats[c_a].value); - break; - case GNUNET_ATS_QUALITY_NET_DELAY: - if (p->ats_delay != ntohl (ats[c_a].value)) - log = GNUNET_YES; - p->ats_delay = ntohl (ats[c_a].value); - break; - case GNUNET_ATS_QUALITY_NET_DISTANCE: - if (p->ats_distance != ntohl (ats[c_a].value)) - log = GNUNET_YES; - p->ats_distance = ntohl (ats[c_a].value); - GNUNET_break (0); - break; - case GNUNET_ATS_COST_WAN: - if (p->ats_cost_wan != ntohl (ats[c_a].value)) - log = GNUNET_YES; - p->ats_cost_wan = ntohl (ats[c_a].value); - break; - case GNUNET_ATS_COST_LAN: - if (p->ats_cost_lan != ntohl (ats[c_a].value)) - log = GNUNET_YES; - p->ats_cost_lan = ntohl (ats[c_a].value); - break; - case GNUNET_ATS_COST_WLAN: - if (p->ats_cost_wlan != ntohl (ats[c_a].value)) - log = GNUNET_YES; - p->ats_cost_wlan = ntohl (ats[c_a].value); - break; - default: - break; - } } - - if ((GNUNET_YES == logging) && (GNUNET_YES == log)) - GNUNET_ATS_TEST_logging_now(); - GNUNET_free(peer_id); + } @@ -747,14 +535,6 @@ main (int argc, char *argv[]) return GNUNET_SYSERR; } - /** - * Core message handler to use for PING/PONG messages - */ - static struct GNUNET_CORE_MessageHandler handlers[] = { - {&comm_handle_ping, TEST_MESSAGE_TYPE_PING, 0 }, - {&comm_handle_pong, TEST_MESSAGE_TYPE_PONG, 0 }, - { NULL, 0, 0 } }; - /** * Setup the topology */ @@ -762,7 +542,7 @@ main (int argc, char *argv[]) num_slaves, num_masters, test_core, &do_benchmark, - NULL, handlers, + NULL, &test_recv_cb, &ats_performance_info_cb);