From 3c2d8c16ca76ac45db471f3c66bc24257b849dd5 Mon Sep 17 00:00:00 2001 From: Matthias Wachs Date: Thu, 14 Apr 2011 16:48:37 +0000 Subject: [PATCH] many changes...improvements --- src/include/gnunet_protocols.h | 5 + src/transport/gnunet-service-transport.c | 438 +++++++++++++++-------- src/transport/test_transport_ats.c | 286 ++++++++++++--- 3 files changed, 539 insertions(+), 190 deletions(-) diff --git a/src/include/gnunet_protocols.h b/src/include/gnunet_protocols.h index d914ba5c8..c1e6ca0ed 100644 --- a/src/include/gnunet_protocols.h +++ b/src/include/gnunet_protocols.h @@ -303,6 +303,11 @@ extern "C" */ #define GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_WELCOME 60 +/** + * Message to force transport to update bandwidth assignment + */ +#define GNUNET_MESSAGE_TYPE_TRANSPORT_ATS 61 + /** * Initial setup message from core client to core. */ diff --git a/src/transport/gnunet-service-transport.c b/src/transport/gnunet-service-transport.c index 7a2d1a647..474cfe2e2 100644 --- a/src/transport/gnunet-service-transport.c +++ b/src/transport/gnunet-service-transport.c @@ -154,6 +154,12 @@ #define VERY_BIG_DOUBLE_VALUE 100000000000LL +#define ATS_NEW 0 +#define ATS_Q_UPDATED 1 +#define ATS_C_UPDATED 2 +#define ATS_QC_UPDATED 3 +#define ATS_UNMODIFIED 4 + /** * List of addresses of other peers */ @@ -875,19 +881,54 @@ struct ATS_peer int t; }; -struct ATS_result +struct ATS_stat { + /** + * result of last GLPK run + * 5 == OPTIMAL + */ + int solution; + + /** + * is problem currently valid and can it be solved + */ + int valid; + + /** + * Number of transport mechanisms in the problem + */ int c_mechs; + + /** + * Number of transport mechanisms in the problem + */ int c_peers; + /** + * row index where quality related rows start + */ int begin_qm; + + /** + * row index where quality related rows end + */ int end_qm; + /** + * row index where ressource cost related rows start + */ int begin_cr; + + /** + * row index where ressource cost related rows end + */ int end_cr; - int solution; - int valid; + int col_d; + int col_u; + int col_r; + int col_qm; + int col_cr; }; struct ATS_ressource_entry @@ -960,44 +1001,94 @@ struct ATS_info * Maximum execution time per calculation */ struct GNUNET_TIME_Relative max_exec_duration; + +#if HAVE_LIBGLPK + /** + * GLPK (MLP) problem object + */ + glp_prob *prob; +#endif + + /** + * task to recalculate the bandwidth assignment + */ + GNUNET_SCHEDULER_TaskIdentifier ats_task; + + /** + * Current state of the GLPK problem + */ + struct ATS_stat stat; + + /** + * mechanisms used in current problem + * needed for problem modification + */ + struct ATS_mechanism * mechanisms; + + /** + * peers used in current problem + * needed for problem modification + */ + struct ATS_peer * peers; + + /** * Maximum number of LP iterations per calculation */ int max_iterations; + /** + * Dump problem to a file? + */ int save_mlp; + + /** + * Dump solution to a file + */ int save_solution; /** - * Ressource costs or quality metrics changed, update matrix + * Ressource costs or quality metrics changed + * update problem before solving */ int modified_resources; /** * Ressource costs or quality metrics changed, update matrix + * update problem before solving */ int modified_quality; /** - * Peers have connected or disconnected, problem has to be recreated + * Peers have connected or disconnected + * problem has to be recreated */ int modified_addr; + /** + * Diversity weight + */ double D; + + /** + * Utility weight + */ double U; - double R; - int v_b_min; - int v_n_min; - GNUNET_SCHEDULER_TaskIdentifier ats_task; + /** + * Relativity weight + */ + double R; - struct ATS_result res; -#if HAVE_LIBGLPK - glp_prob *prob; -#endif + /** + * Minimum bandwidth per peer + */ + int v_b_min; - struct ATS_mechanism * mechanisms; - struct ATS_peer * peers; + /** + * Minimum number of connections per peer + */ + int v_n_min; }; @@ -5103,9 +5194,11 @@ plugin_env_receive (void *cls, const struct GNUNET_PeerIdentity *peer, distance = ntohl(ats_data[c].value); } } + /* notify ATS about incoming data */ //ats_notify_ats_data(peer, ats_data); + if (message != NULL) { if ( (session != NULL) || @@ -5132,6 +5225,7 @@ plugin_env_receive (void *cls, const struct GNUNET_PeerIdentity *peer, } /* update traffic received amount ... */ msize = ntohs (message->size); + GNUNET_STATISTICS_update (stats, gettext_noop ("# bytes received from other peers"), msize, @@ -5159,6 +5253,27 @@ plugin_env_receive (void *cls, const struct GNUNET_PeerIdentity *peer, GNUNET_NO); return GNUNET_CONSTANTS_QUOTA_VIOLATION_TIMEOUT; } + if ((ntohs(message->type) == GNUNET_MESSAGE_TYPE_TRANSPORT_ATS) && + (ntohs(message->size) == (sizeof (struct GNUNET_MessageHeader) + sizeof (uint32_t)))) + { + uint32_t value = ntohl(*((uint32_t *) &message[1])); + //GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "GNUNET_MESSAGE_TYPE_TRANSPORT_ATS: %i \n", value); + /* Force ressource and quality update */ + if (value == 4) + { + ats->modified_resources = GNUNET_YES; + ats->modified_quality = GNUNET_YES; + } + /* Force cost update */ + if (value == 3) + ats->modified_resources = GNUNET_YES; + /* Force quality update */ + if (value == 2) + ats->modified_quality = GNUNET_YES; + /* Force full rebuild */ + if (value == 1) + ats->modified_addr = GNUNET_YES; + } #if DEBUG_PING_PONG GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, @@ -5182,6 +5297,8 @@ plugin_env_receive (void *cls, const struct GNUNET_PeerIdentity *peer, case GNUNET_MESSAGE_TYPE_TRANSPORT_PONG: handle_pong (plugin, message, peer, sender_address, sender_address_len); break; + case GNUNET_MESSAGE_TYPE_TRANSPORT_ATS: + break; default: handle_payload_message (message, n); break; @@ -5902,7 +6019,7 @@ return cont; } -static void ats_solve_problem (unsigned int max_it, unsigned int max_dur, unsigned int c_peers, unsigned int c_mechs, struct ATS_result *res) +static void ats_solve_problem (unsigned int max_it, unsigned int max_dur, unsigned int c_peers, unsigned int c_mechs, struct ATS_stat *stat) { int result; int solution; @@ -5938,10 +6055,10 @@ static void ats_solve_problem (unsigned int max_it, unsigned int max_dur, unsig #endif result = glp_intopt (prob, &opt_mlp); solution = glp_mip_status (prob); - res->solution = solution; - res->valid = GNUNET_NO; + stat->solution = solution; + stat->valid = GNUNET_NO; if (ats_evaluate_results(result, solution, "MLP") == GNUNET_YES) - res->valid = GNUNET_YES; + stat->valid = GNUNET_YES; /* done */ } @@ -6013,7 +6130,7 @@ static void ats_delete_problem () { int c; - for (c=0; c< (ats->res).c_mechs; c++) + for (c=0; c< (ats->stat).c_mechs; c++) GNUNET_free_non_null (ats->mechanisms[c].rc); if (ats->mechanisms!=NULL) @@ -6033,14 +6150,14 @@ static void ats_delete_problem () ats->prob = NULL; } - ats->res.begin_cr = GNUNET_SYSERR; - ats->res.begin_qm = GNUNET_SYSERR; - ats->res.c_mechs = 0; - ats->res.c_peers = 0; - ats->res.end_cr = GNUNET_SYSERR; - ats->res.end_qm = GNUNET_SYSERR; - ats->res.solution = GNUNET_SYSERR; - ats->res.valid = GNUNET_SYSERR; + ats->stat.begin_cr = GNUNET_SYSERR; + ats->stat.begin_qm = GNUNET_SYSERR; + ats->stat.c_mechs = 0; + ats->stat.c_peers = 0; + ats->stat.end_cr = GNUNET_SYSERR; + ats->stat.end_qm = GNUNET_SYSERR; + ats->stat.solution = GNUNET_SYSERR; + ats->stat.valid = GNUNET_SYSERR; } static void ats_update_problem_qm () @@ -6050,11 +6167,12 @@ static void ats_update_problem_qm () int c, c2; int c_q_metrics = available_quality_metrics; - int *ja = GNUNET_malloc ((1 + ats->res.c_mechs*2 + 3 + available_quality_metrics) * sizeof (int)); - double *ar = GNUNET_malloc ((1 + ats->res.c_mechs*2 + 3 + available_quality_metrics) * sizeof (double)); - if (ats->res.c_mechs>10) + int *ja = GNUNET_malloc ((1 + ats->stat.c_mechs*2 + 3 + available_quality_metrics) * sizeof (int)); + double *ar = GNUNET_malloc ((1 + ats->stat.c_mechs*2 + 3 + available_quality_metrics) * sizeof (double)); +#if DEBUG_ATS GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Updating problem quality metrics\n"); - row_index = ats->res.begin_qm; +#endif + row_index = ats->stat.begin_qm; for (c=1; c <= c_q_metrics; c++) { @@ -6065,7 +6183,7 @@ static void ats_update_problem_qm () #endif glp_set_row_bnds(ats->prob, row_index, GLP_FX, 0.0, 0.0); - for (c2=1; c2<=ats->res.c_mechs; c2++) + for (c2=1; c2<=ats->stat.c_mechs; c2++) { ja[array_index] = c2; @@ -6102,7 +6220,7 @@ static void ats_update_problem_qm () #endif array_index++; } - ja[array_index] = (2*ats->res.c_mechs) + 3 +c; + ja[array_index] = ats->stat.col_qm + c - 1; ar[array_index] = -1; #if VERBOSE_ATS @@ -6128,11 +6246,11 @@ static void ats_update_problem_cr () int c, c2; double ct_max, ct_min; - int *ja = GNUNET_malloc ((1 + ats->res.c_mechs*2 + 3 + available_quality_metrics) * sizeof (int)); - double *ar = GNUNET_malloc ((1 + ats->res.c_mechs*2 + 3 + available_quality_metrics) * sizeof (double)); + int *ja = GNUNET_malloc ((1 + ats->stat.c_mechs*2 + 3 + available_quality_metrics) * sizeof (int)); + double *ar = GNUNET_malloc ((1 + ats->stat.c_mechs*2 + 3 + available_quality_metrics) * sizeof (double)); GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Updating problem quality metrics\n"); - row_index = ats->res.begin_cr; + row_index = ats->stat.begin_cr; for (c=0; cprob, row_index, GLP_DB, ct_min, ct_max); - for (c2=1; c2<=ats->res.c_mechs; c2++) + for (c2=1; c2<=ats->stat.c_mechs; c2++) { double value = 0; ja[array_index] = c2; value = ats->mechanisms[c2].addr->ressources[c].c; ar[array_index] = value; #if VERBOSE_ATS - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "[index]=[%i]: [%i,%i]=%f \n",array_index, rowrow_indexs, ja[array_index], ar[array_index]); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "[index]=[%i]: [%i,%i]=%f \n",array_index, row_index, ja[array_index], ar[array_index]); #endif array_index++; } @@ -6173,10 +6291,10 @@ static void ats_update_problem_cr () * @param R weight for relativity * @param v_b_min minimal bandwidth per peer * @param v_n_min minimum number of connections - * @param res result struct + * @param stat result struct * @return GNUNET_SYSERR if glpk is not available, number of mechanisms used */ -static int ats_create_problem (double D, double U, double R, int v_b_min, int v_n_min, struct ATS_result *res) +static int ats_create_problem (double D, double U, double R, int v_b_min, int v_n_min, struct ATS_stat *stat) { if (ats->prob != NULL) glp_delete_prob(ats->prob); @@ -6220,9 +6338,9 @@ static int ats_create_problem (double D, double U, double R, int v_b_min, int v_ #if DEBUG_ATS GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No addresses for bw distribution available\n", c_peers); #endif - res->valid = GNUNET_NO; - res->c_peers = 0; - res->c_mechs = 0; + stat->valid = GNUNET_NO; + stat->c_peers = 0; + stat->c_mechs = 0; return GNUNET_SYSERR; } @@ -6393,7 +6511,7 @@ static int ats_create_problem (double D, double U, double R, int v_b_min, int v_ double ct_max = VERY_BIG_DOUBLE_VALUE; double ct_min = 0.0; - res->begin_cr = array_index; + stat->begin_cr = array_index; for (c=0; cend_cr = array_index--; + stat->end_cr = array_index--; /* Constraint 5: min number of connections*/ glp_add_rows(ats->prob, 1); @@ -6445,10 +6563,13 @@ static int ats_create_problem (double D, double U, double R, int v_b_min, int v_ // adding columns // Constraint 6: optimize for diversity - glp_add_cols(ats->prob, 1); - glp_set_col_name(ats->prob, (2*c_mechs) + 1, "d"); - glp_set_obj_coef(ats->prob, (2*c_mechs) + 1, D); - glp_set_col_bnds(ats->prob, (2*c_mechs) + 1, GLP_LO, 0.0, 0.0); + int col_d; + col_d = glp_add_cols(ats->prob, 1); + stat->col_d = col_d; + //GNUNET_assert (col_d == (2*c_mechs) + 1); + glp_set_col_name(ats->prob, col_d, "d"); + glp_set_obj_coef(ats->prob, col_d, D); + glp_set_col_bnds(ats->prob, col_d, GLP_LO, 0.0, 0.0); glp_add_rows(ats->prob, 1); #if VERBOSE_ATS GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "bounds [row]=[%i] \n",row_index); @@ -6466,7 +6587,7 @@ static int ats_create_problem (double D, double U, double R, int v_b_min, int v_ array_index++; } ia[array_index] = row_index; - ja[array_index] = (2*c_mechs) + 1; + ja[array_index] = col_d; ar[array_index] = -1; #if VERBOSE_ATS GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "[index]=[%i]: [%i,%i]=%f \n",array_index, ia[array_index], ja[array_index], ar[array_index]); @@ -6474,81 +6595,22 @@ static int ats_create_problem (double D, double U, double R, int v_b_min, int v_ array_index++; row_index ++; - // Constraint 8: optimize bandwidth utility - glp_add_cols(ats->prob, 1); - glp_set_col_name(ats->prob, (2*c_mechs) + 2, "u"); - glp_set_obj_coef(ats->prob, (2*c_mechs) + 2, U); - glp_set_col_bnds(ats->prob, (2*c_mechs) + 2, GLP_LO, 0.0, 0.0); - glp_add_rows(ats->prob, 1); -#if VERBOSE_ATS - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "bounds [row]=[%i] \n",row_index); -#endif - glp_set_row_bnds(ats->prob, row_index, GLP_FX, 0.0, 0.0); - for (c=1; c<=c_mechs; c++) - { - ia[array_index] = row_index; - ja[array_index] = c; - ar[array_index] = mechanisms[c].peer->f; -#if VERBOSE_ATS - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "[index]=[%i]: [%i,%i]=%f \n",array_index, ia[array_index], ja[array_index], ar[array_index]); -#endif - array_index++; - } - ia[array_index] = row_index; - ja[array_index] = (2*c_mechs) + 2; - ar[array_index] = -1; -#if VERBOSE_ATS - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "[index]=[%i]: [%i,%i]=%f \n",array_index, ia[array_index], ja[array_index], ar[array_index]); -#endif - - array_index++; - row_index ++; - - // Constraint 9: optimize relativity - glp_add_cols(ats->prob, 1); - glp_set_col_name(ats->prob, (2*c_mechs) + 3, "r"); - glp_set_obj_coef(ats->prob, (2*c_mechs) + 3, R); - glp_set_col_bnds(ats->prob, (2*c_mechs) + 3, GLP_LO, 0.0, 0.0); - glp_add_rows(ats->prob, c_peers); - for (c=1; c<=c_peers; c++) - { - glp_set_row_bnds(ats->prob, row_index, GLP_LO, 0.0, 0.0); - - struct ATS_mechanism *m = peers[c].m_head; - while (m!=NULL) - { - ia[array_index] = row_index; - ja[array_index] = m->col_index; - ar[array_index] = 1 / mechanisms[c].peer->f; -#if VERBOSE_ATS - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "[index]=[%i]: [%i,%i]=%f \n",array_index, ia[array_index], ja[array_index], ar[array_index]); -#endif - array_index++; - m = m->next; - } - ia[array_index] = row_index; - ja[array_index] = (2*c_mechs) + 3; - ar[array_index] = -1; -#if VERBOSE_ATS - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "[index]=[%i]: [%i,%i]=%f \n",array_index, ia[array_index], ja[array_index], ar[array_index]); -#endif - array_index++; - - row_index++; - } // Constraint 7: optimize for quality - glp_add_cols(ats->prob, c_q_metrics); - for (c=1; c<= c_q_metrics; c++) + int col_qm; + col_qm = glp_add_cols(ats->prob, c_q_metrics); + stat->col_qm = col_qm; + //GNUNET_assert (col_qm == (2*c_mechs) + 3 + 1); + for (c=0; c< c_q_metrics; c++) { - GNUNET_asprintf(&name, "Q_%s",qm[c-1].name); - glp_set_col_name(ats->prob, (2*c_mechs) + 3 + c, name); - glp_set_col_bnds(ats->prob, (2*c_mechs) + 3 + c, GLP_LO, 0.0, 0.0); + GNUNET_asprintf(&name, "Q_%s",qm[c].name); + glp_set_col_name(ats->prob, col_qm + c, name); + glp_set_col_bnds(ats->prob, col_qm + c, GLP_LO, 0.0, 0.0); GNUNET_free (name); - glp_set_obj_coef(ats->prob, (2*c_mechs) + 3 + c, Q[c]); + glp_set_obj_coef(ats->prob, col_qm + c, Q[c]); } glp_add_rows(ats->prob, available_quality_metrics); - res->begin_qm = row_index; + stat->begin_qm = row_index; for (c=1; c <= c_q_metrics; c++) { #if VERBOSE_ATS @@ -6596,23 +6658,92 @@ static int ats_create_problem (double D, double U, double R, int v_b_min, int v_ } ia[array_index] = row_index; - ja[array_index] = (2*c_mechs) + 3 +c; + ja[array_index] = col_qm + c - 1; + ar[array_index] = -1; +#if VERBOSE_ATS + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "[index]=[%i]: [%i,%i]=%f \n",array_index, ia[array_index], ja[array_index], ar[array_index]); +#endif + array_index++; + row_index++; + } + stat->end_qm = row_index-1; + + // Constraint 8: optimize bandwidth utility + int col_u; + col_u = glp_add_cols(ats->prob, 1); + stat->col_u = col_u; + //GNUNET_assert (col_u == (2*c_mechs) + 2); + glp_set_col_name(ats->prob, col_u, "u"); + glp_set_obj_coef(ats->prob, col_u, U); + glp_set_col_bnds(ats->prob, col_u, GLP_LO, 0.0, 0.0); + glp_add_rows(ats->prob, 1); +#if VERBOSE_ATS + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "bounds [row]=[%i] \n",row_index); +#endif + glp_set_row_bnds(ats->prob, row_index, GLP_FX, 0.0, 0.0); + for (c=1; c<=c_mechs; c++) + { + ia[array_index] = row_index; + ja[array_index] = c; + ar[array_index] = mechanisms[c].peer->f; +#if VERBOSE_ATS + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "[index]=[%i]: [%i,%i]=%f \n",array_index, ia[array_index], ja[array_index], ar[array_index]); +#endif + array_index++; + } + ia[array_index] = row_index; + ja[array_index] = col_u; + ar[array_index] = -1; +#if VERBOSE_ATS + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "[index]=[%i]: [%i,%i]=%f \n",array_index, ia[array_index], ja[array_index], ar[array_index]); +#endif + + array_index++; + row_index ++; + + // Constraint 9: optimize relativity + int col_r; + col_r = glp_add_cols(ats->prob, 1); + stat->col_r = col_r; + //GNUNET_assert (col_r == (2*c_mechs) + 3); + glp_set_col_name(ats->prob, col_r, "r"); + glp_set_obj_coef(ats->prob, col_r, R); + glp_set_col_bnds(ats->prob, col_r, GLP_LO, 0.0, 0.0); + glp_add_rows(ats->prob, c_peers); + for (c=1; c<=c_peers; c++) + { + glp_set_row_bnds(ats->prob, row_index, GLP_LO, 0.0, 0.0); + + struct ATS_mechanism *m = peers[c].m_head; + while (m!=NULL) + { + ia[array_index] = row_index; + ja[array_index] = m->col_index; + ar[array_index] = 1 / mechanisms[c].peer->f; +#if VERBOSE_ATS + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "[index]=[%i]: [%i,%i]=%f \n",array_index, ia[array_index], ja[array_index], ar[array_index]); +#endif + array_index++; + m = m->next; + } + ia[array_index] = row_index; + ja[array_index] = col_r; ar[array_index] = -1; #if VERBOSE_ATS GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "[index]=[%i]: [%i,%i]=%f \n",array_index, ia[array_index], ja[array_index], ar[array_index]); #endif array_index++; + row_index++; } - res->end_qm = row_index-1; /* Loading the matrix */ glp_load_matrix(ats->prob, array_index-1, ia, ja, ar); - res->c_mechs = c_mechs; - res->c_peers = c_peers; - res->solution = 0; - res->valid = GNUNET_YES; + stat->c_mechs = c_mechs; + stat->c_peers = c_peers; + stat->solution = 0; + stat->valid = GNUNET_YES; /* clean up */ @@ -6640,8 +6771,10 @@ static void ats_calculate_bandwidth_distribution () { #if HAVE_LIBGLPK +#endif struct GNUNET_TIME_Absolute start; - struct GNUNET_TIME_Relative duration; + struct GNUNET_TIME_Relative creation; + struct GNUNET_TIME_Relative solving; struct GNUNET_TIME_Relative delta = GNUNET_TIME_absolute_get_difference(ats->last,GNUNET_TIME_absolute_get()); if (delta.rel_value < ats->min_delta.rel_value) @@ -6661,11 +6794,10 @@ ats_calculate_bandwidth_distribution () start = GNUNET_TIME_absolute_get(); if ((ats->modified_addr == GNUNET_YES) || (ats->prob==NULL)) { - ats->modified_addr = GNUNET_NO; ats_delete_problem (); - ats_create_problem (ats->D, ats->U, ats->R, ats->v_b_min, ats->v_n_min, &ats->res); + ats_create_problem (ats->D, ats->U, ats->R, ats->v_b_min, ats->v_n_min, &ats->stat); #if DEBUG_ATS - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Peers/Addresses were modified... new problem: %i peer, %i mechs\n", ats->res.c_peers, ats->res.c_mechs); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Peers/Addresses were modified... new problem: %i peer, %i mechs\n", ats->stat.c_peers, ats->stat.c_mechs); #endif } else if (ats->modified_resources == GNUNET_YES) @@ -6680,31 +6812,43 @@ ats_calculate_bandwidth_distribution () else GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Problem is unmodified\n"); #endif - if (ats->res.valid == GNUNET_YES) + creation = GNUNET_TIME_absolute_get_difference(start,GNUNET_TIME_absolute_get()); + start = GNUNET_TIME_absolute_get(); + + if (ats->stat.valid == GNUNET_YES) { - ats->res.solution = GNUNET_SYSERR; - ats_solve_problem(ats->max_iterations, ats->max_exec_duration.rel_value, ats->res.c_peers, ats->res.c_mechs, &ats->res); - if (ats->res.solution != 5) - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Problem solution is not optimal: %i\n", ats->res.solution); + ats->stat.solution = GNUNET_SYSERR; + ats_solve_problem(ats->max_iterations, ats->max_exec_duration.rel_value, ats->stat.c_peers, ats->stat.c_mechs, &ats->stat); + if (ats->stat.solution != 5) + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Problem solution is not optimal: %i\n", ats->stat.solution); } - duration = GNUNET_TIME_absolute_get_difference(start,GNUNET_TIME_absolute_get()); + solving = GNUNET_TIME_absolute_get_difference(start,GNUNET_TIME_absolute_get()); - if (ats->res.valid == GNUNET_YES) + if (ats->stat.valid == GNUNET_YES) { #if DEBUG_ATS + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "MLP: creation time in [ms] %llu execution time in [ms] %llu for %i mechanisms\n", creation.rel_value, solving.rel_value, ats->stat.c_mechs); #endif - if (ats->res.c_mechs > 8) - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "MLP execution time in [ms] for %i mechanisms: %llu\n", ats->res.c_mechs, duration.rel_value); - - GNUNET_STATISTICS_set (stats, "ATS duration", duration.rel_value, GNUNET_NO); - GNUNET_STATISTICS_set (stats, "ATS mechanisms", ats->res.c_mechs, GNUNET_NO); - GNUNET_STATISTICS_set (stats, "ATS peers", ats->res.c_peers, GNUNET_NO); - GNUNET_STATISTICS_set (stats, "ATS solution", ats->res.solution, GNUNET_NO); + GNUNET_STATISTICS_set (stats, "ATS duration", solving.rel_value + creation.rel_value, GNUNET_NO); + GNUNET_STATISTICS_set (stats, "ATS mechanisms", ats->stat.c_mechs, GNUNET_NO); + GNUNET_STATISTICS_set (stats, "ATS peers", ats->stat.c_peers, GNUNET_NO); + GNUNET_STATISTICS_set (stats, "ATS solution", ats->stat.solution, GNUNET_NO); GNUNET_STATISTICS_set (stats, "ATS timestamp", start.abs_value, GNUNET_NO); + if ((ats->modified_addr == GNUNET_YES) || (ats->prob==NULL)) + GNUNET_STATISTICS_set (stats, "ATS state",ATS_NEW, GNUNET_NO); + else if ((ats->modified_resources == GNUNET_YES) && (ats->modified_quality == GNUNET_NO)) + GNUNET_STATISTICS_set (stats, "ATS state", ATS_C_UPDATED, GNUNET_NO); + else if ((ats->modified_resources == GNUNET_NO) && (ats->modified_quality == GNUNET_YES)) + GNUNET_STATISTICS_set (stats, "ATS state", ATS_Q_UPDATED, GNUNET_NO); + else if ((ats->modified_resources == GNUNET_YES) && (ats->modified_quality == GNUNET_YES)) + GNUNET_STATISTICS_set (stats, "ATS state", ATS_QC_UPDATED, GNUNET_NO); + else + GNUNET_STATISTICS_set (stats, "ATS state", ATS_UNMODIFIED, GNUNET_NO); + } #if DEBUG_ATS - else if (ats->res.valid == GNUNET_NO) + else if (ats->stat.valid == GNUNET_NO) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "MLP not executed: no addresses\n"); } @@ -6714,8 +6858,6 @@ ats_calculate_bandwidth_distribution () ats->modified_addr = GNUNET_NO; ats->modified_resources = GNUNET_NO; ats->modified_quality = GNUNET_NO; - -#endif } @@ -6757,7 +6899,7 @@ void ats_init () ats->ats_task = GNUNET_SCHEDULER_NO_TASK; #if !HAVE_LIBGLPK - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "GLPK not installed, ATS not active"); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "GLPK not installed, ATS not active\n"); return; #endif diff --git a/src/transport/test_transport_ats.c b/src/transport/test_transport_ats.c index 5c5334812..e83080a1a 100644 --- a/src/transport/test_transport_ats.c +++ b/src/transport/test_transport_ats.c @@ -23,6 +23,7 @@ */ #include "platform.h" #include "gnunet_testing_lib.h" +#include "gnunet_transport_service.h" #include "gnunet_scheduler_lib.h" #include "gauger.h" @@ -33,7 +34,13 @@ #define DELAY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 300) #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 300) +#define SEND_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1) +#define ATS_NEW 0 +#define ATS_Q_UPDATED 1 +#define ATS_C_UPDATED 2 +#define ATS_QC_UPDATED 3 +#define ATS_UNMODIFIED 4 static int ok; @@ -47,7 +54,9 @@ static struct GNUNET_TESTING_PeerGroup *pg; static GNUNET_SCHEDULER_TaskIdentifier shutdown_task; static GNUNET_SCHEDULER_TaskIdentifier stats_task; +static GNUNET_SCHEDULER_TaskIdentifier send_task; struct GNUNET_TESTING_Daemon * master_deamon; +struct GNUNET_TESTING_Daemon * ping_deamon; struct GNUNET_STATISTICS_Handle * stats; @@ -58,14 +67,31 @@ struct TEST_result uint64_t mechs; uint64_t peers; uint64_t solution; + uint64_t state; }; -static int r_index; -//static int measurements; +struct TestMessage +{ + struct GNUNET_MessageHeader header; + uint32_t num; +}; + + +static int count; +static int c_new; +static int c_unmodified; +static int c_modified; static int connected; static int peers; -static struct TEST_result results[MEASUREMENTS]; +static int force_q_updates; +static int force_rebuild; +static int send_msg; + +static struct TEST_result results_new [MEASUREMENTS+1]; +static struct TEST_result results_modified [MEASUREMENTS+1]; +static struct TEST_result results_unmodified[MEASUREMENTS+1]; +static struct TEST_result current; static struct GNUNET_STATISTICS_GetHandle * s_solution; static struct GNUNET_STATISTICS_GetHandle * s_time; @@ -73,6 +99,10 @@ static struct GNUNET_STATISTICS_GetHandle * s_peers; static struct GNUNET_STATISTICS_GetHandle * s_mechs; static struct GNUNET_STATISTICS_GetHandle * s_duration; static struct GNUNET_STATISTICS_GetHandle * s_invalid; +static struct GNUNET_STATISTICS_GetHandle * s_state; + +struct GNUNET_TRANSPORT_TransmitHandle * t; +struct GNUNET_TRANSPORT_Handle * th; /** * Check whether peers successfully shut down. @@ -112,6 +142,19 @@ static void shutdown_peers() GNUNET_SCHEDULER_cancel(stats_task); stats_task = GNUNET_SCHEDULER_NO_TASK; } + if (send_task != GNUNET_SCHEDULER_NO_TASK) + { + GNUNET_SCHEDULER_cancel(send_task); + send_task = GNUNET_SCHEDULER_NO_TASK; + } + + if (t!=NULL) + { + GNUNET_TRANSPORT_notify_transmit_ready_cancel(t); + t = NULL; + } + + GNUNET_TRANSPORT_disconnect(th); if (s_time != NULL) { @@ -143,6 +186,11 @@ static void shutdown_peers() GNUNET_STATISTICS_get_cancel(s_invalid); s_invalid = NULL; } + if (s_state != NULL) + { + GNUNET_STATISTICS_get_cancel(s_state); + s_state = NULL; + } GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL); } @@ -150,34 +198,62 @@ static void shutdown_peers() static void evaluate_measurements() { int c; - char * output = NULL; - char * temp; - double average; + double average ; double stddev; - double measure = MEASUREMENTS; - for (c=0; c= MEASUREMENTS) + if (current.state == ATS_NEW) + { + if (c_new < MEASUREMENTS) + { + results_new[c_new] = current; + c_new++; + } + else + { + force_rebuild = GNUNET_NO; + force_q_updates = GNUNET_NO; + send_msg = GNUNET_NO; + } + } + if (current.state == ATS_UNMODIFIED) + { + if (c_unmodified < MEASUREMENTS) + { + results_unmodified[c_unmodified] = current; + c_unmodified++; + } + + } + if (current.state == ATS_Q_UPDATED) + { + if (c_modified < MEASUREMENTS) + { + results_modified[c_modified] = current; + c_modified++; + } + else + { + force_q_updates = GNUNET_NO; + force_rebuild = GNUNET_YES; + } + } + count ++; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "(new: %i / modified: %i / unmodified: %i) of %i \n", c_new, c_modified, c_unmodified , MEASUREMENTS); + if ((count > MEASUREMENTS * 4) || ((c_modified >= MEASUREMENTS) && (c_new >= MEASUREMENTS) && (c_unmodified >= MEASUREMENTS))) { fprintf(stdout, "\n"); if (stats_task != GNUNET_SCHEDULER_NO_TASK) @@ -252,35 +378,51 @@ int stats_cb (void *cls, evaluate_measurements(); return GNUNET_SYSERR; } - fprintf(stdout, ".."); - results[r_index].timestamp = value; + printed = GNUNET_NO; + current.timestamp = value; return GNUNET_OK; } } if (0 == strcmp (name,"ATS solution")) { - results[r_index].solution = value; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "[%i] ATS solution: %s %llu \n", r_index, name, value); + current.solution = value; + if (printed == GNUNET_NO) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "[%i] %s: %llu \n", count, name, value); } if (0 == strcmp (name,"ATS peers")) { - results[r_index].peers = value; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "[%i] ATS peers: %s %llu \n", r_index, name, value); + current.peers = value; + if (printed == GNUNET_NO) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "[%i] %s: %llu \n", count, name, value); } if (0 == strcmp (name,"ATS mechanisms")) { - results[r_index].mechs = value; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "[%i] ATS mechanisms: %s %llu \n", r_index, name, value); + current.mechs = value; + if (printed == GNUNET_NO) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "[%i] %s: %llu \n", count, name, value); } if (0 == strcmp (name,"ATS duration")) { - results[r_index].duration = value; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "[%i] ATS duration: %s %llu \n", r_index, name, value); + current.duration = value; + if (printed == GNUNET_NO) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "[%i] %s: %llu \n", count, name, value); + } + if (0 == strcmp (name,"ATS state")) + { + current.state = value; + char * cont; + if (value == ATS_NEW) + cont = "NEW"; + if (value == ATS_C_UPDATED) + cont = "C_UPDATED"; + if (value == ATS_Q_UPDATED) + cont = "Q_UPDATED"; + if (value == ATS_QC_UPDATED) + cont = "QC_UPDATED"; + if (value == ATS_UNMODIFIED) + cont = "UNMODIFIED"; + if (printed == GNUNET_NO) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "[%i] ATS state: %s\n", count, cont); } } return GNUNET_OK; @@ -301,7 +443,7 @@ stats_get_task (void *cls, s_peers = GNUNET_STATISTICS_get (stats, "transport", "ATS peers", TIMEOUT, NULL, &stats_cb, NULL); s_mechs = GNUNET_STATISTICS_get (stats, "transport", "ATS mechanisms", TIMEOUT, NULL, &stats_cb, NULL); s_invalid = GNUNET_STATISTICS_get (stats, "transport", "ATS invalid solutions", TIMEOUT, NULL, &stats_cb, NULL); - + s_state = GNUNET_STATISTICS_get (stats, "transport", "ATS state", TIMEOUT, NULL, &stats_cb, NULL); stats_task = GNUNET_SCHEDULER_add_delayed(GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 250), &stats_get_task, NULL); } @@ -326,6 +468,46 @@ static void connect_peers() } +size_t send_dummy_data_task (void *cls, size_t size, void *buf) +{ + + int s = sizeof (struct TestMessage); + struct TestMessage hdr; + + hdr.header.size = htons (s); + hdr.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_ATS); + if (force_rebuild) + hdr.num = htonl (1); + if (force_q_updates) + hdr.num = htonl (2); + + + memcpy (buf,&hdr, s); + // GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Sent bytes: %i of %i\n", s, s); + t = NULL; + return s; +} + +void send_task_f (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + send_task = GNUNET_SCHEDULER_NO_TASK; + if ( (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) + return; + + if (t!=NULL) + { + GNUNET_TRANSPORT_notify_transmit_ready_cancel(t); + t = NULL; + } + // GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Sent bytes: %i to %s\n", size, GNUNET_i2s(&master_deamon->id)); + if (send_msg == GNUNET_YES) + t = GNUNET_TRANSPORT_notify_transmit_ready(th, &master_deamon->id, sizeof (struct TestMessage), 0, SEND_TIMEOUT, &send_dummy_data_task, NULL); + send_task = GNUNET_SCHEDULER_add_delayed(GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MILLISECONDS,1000), &send_task_f, NULL); +} + + + void daemon_connect_cb(void *cls, const struct GNUNET_PeerIdentity *first, const struct GNUNET_PeerIdentity *second, @@ -342,6 +524,15 @@ void daemon_connect_cb(void *cls, GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected peers `%s'<->`%s' (%i/%i)\n", firstc, secondc, connected, peers-1); GNUNET_free(firstc); GNUNET_free(secondc); + + if (((first_daemon == ping_deamon) || (second_daemon == ping_deamon)) && (master_deamon != NULL) && (ping_deamon != NULL)) + { + th = GNUNET_TRANSPORT_connect (ping_deamon->cfg,&ping_deamon->id, NULL, NULL,NULL, NULL); + t = NULL; + force_q_updates = GNUNET_YES; + send_msg = GNUNET_YES; + send_task = GNUNET_SCHEDULER_add_now(&send_task_f, NULL); + } } void cont_cb (void *cls, int success) @@ -390,7 +581,13 @@ daemon_start_cb (void *cls, if (peers_left == 0) { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + if (ping_deamon == NULL) + { + ping_deamon = d; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ping peer `%s' '%s'\n", GNUNET_i2s(id), d->cfgfile); + } + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All peers started successfully!\n"); connect_peers(); ok = 0; @@ -449,6 +646,11 @@ check () int main (int argc, char *argv[]) { +#if !HAVE_LIBGLPK + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "GLPK not installed, exiting testcase\n"); + return 0; +#endif + int ret; GNUNET_log_setup ("test-transport-ats", -- 2.25.1