/** * Delete an address * * If session != 0, just the session is deleted, the address itself still exists * If session == 0, remove full address * If session == 0 and addrlen == 0, destroy inbound address * * @param cls unused * @param key unused * @param value the 'struct ATS_Address' * @return GNUNET_OK (continue to iterate) */ static int destroy_by_session_id (void *cls, const struct GNUNET_HashCode * key, void *value) { const struct ATS_Address *info = cls; struct ATS_Address *aa = value; GNUNET_assert (0 == memcmp (&aa->peer, &info->peer, sizeof (struct GNUNET_PeerIdentity))); /* session == 0, remove full address */ if ((info->session_id == 0) && (0 == strcmp (info->plugin, aa->plugin)) && (aa->addr_len == info->addr_len) && (0 == memcmp (info->addr, aa->addr, aa->addr_len))) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Deleting address for peer `%s': `%s' %u\n", GNUNET_i2s (&aa->peer), aa->plugin, aa->session_id); if (GNUNET_YES == destroy_address (aa)) recalculate_assigned_bw (); return GNUNET_OK; } /* session != 0, just remove session */ if (aa->session_id != info->session_id) return GNUNET_OK; /* irrelevant */ if (aa->session_id != 0) GNUNET_break (0 == strcmp (info->plugin, aa->plugin)); /* session died */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Deleting session for peer `%s': `%s' %u\n", GNUNET_i2s (&aa->peer), aa->plugin, aa->session_id); aa->session_id = 0; if (GNUNET_YES == aa->active) { aa->active = GNUNET_NO; active_addr_count--; recalculate_assigned_bw (); } /* session == 0 and addrlen == 0 : destroy address */ if (aa->addr_len == 0) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Deleting session and address for peer `%s': `%s' %u\n", GNUNET_i2s (&aa->peer), aa->plugin, aa->session_id); (void) destroy_address (aa); } else { /* session was set to 0, update address */ #if HAVE_LIBGLPK if (ats_mode == MLP) GAS_mlp_address_update (mlp, addresses, aa); #endif } return GNUNET_OK; }
int GAS_addresses_in_use (const struct GNUNET_PeerIdentity *peer, const char *plugin_name, const void *plugin_addr, size_t plugin_addr_len, uint32_t session_id, int in_use) { #if DEBUG_ATS GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message for peer `%s': %i\n", "ADDRESS_IN_USE", GNUNET_i2s (peer), in_use); #endif struct ATS_Address *old; if (GNUNET_NO == running) return GNUNET_SYSERR; old = lookup_address (peer, plugin_name, plugin_addr, plugin_addr_len, session_id, NULL, 0); if (NULL == old) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Trying to set unknown address `%s', %s %u %s \n", GNUNET_i2s (peer), plugin_name, session_id, (GNUNET_NO == in_use) ? "NO" : "YES"); GNUNET_break (0); return GNUNET_SYSERR; } if (old->used == in_use) { GNUNET_break (0); GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Address in use called multiple times for peer `%s': %s -> %s \n", GNUNET_i2s (peer), (GNUNET_NO == old->used) ? "NO" : "YES", (GNUNET_NO == in_use) ? "NO" : "YES"); return GNUNET_SYSERR; } old->used = in_use; #if HAVE_LIBGLPK if (ats_mode == MLP) GAS_mlp_address_update (mlp, addresses, old); #endif return GNUNET_OK; }
static void check (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { #if !HAVE_LIBGLPK GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "GLPK not installed!"); ret = 1; return; #endif struct ATS_Address addr[10]; struct ATS_PreferedAddress *res[10]; struct MLP_information *mlpi; struct GAS_MLP_SolutionContext ctx; stats = GNUNET_STATISTICS_create("ats", cfg); addresses = GNUNET_CONTAINER_multihashmap_create (10); mlp = GAS_mlp_init (cfg, NULL, MLP_MAX_EXEC_DURATION, MLP_MAX_ITERATIONS); mlp->auto_solve = GNUNET_NO; struct GNUNET_PeerIdentity p[10]; /* Creating peer 1 */ GNUNET_CRYPTO_hash_create_random(GNUNET_CRYPTO_QUALITY_WEAK, &p[0].hashPubKey); /* Creating peer 1 address 1 */ addr[0].peer.hashPubKey = p[0].hashPubKey; struct GNUNET_ATS_Information a1_ats[3]; set_ats (&a1_ats[0], GNUNET_ATS_QUALITY_NET_DISTANCE, 1); set_ats (&a1_ats[1], GNUNET_ATS_QUALITY_NET_DELAY, 0); set_ats (&a1_ats[2], GNUNET_ATS_ARRAY_TERMINATOR, 0); create_address (&addr[0], "dummy", 3, &a1_ats[0]); addr[0].atsp_network_type = GNUNET_ATS_NET_LAN; GNUNET_CONTAINER_multihashmap_put(addresses, &addr[0].peer.hashPubKey, &addr[0], GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); /* Add peer 1 address 1 */ GAS_mlp_address_update (mlp, addresses, &addr[0]); mlpi = addr[0].mlp_information; GNUNET_assert (mlp != NULL); GNUNET_assert (mlp->addr_in_problem == 1); /* Update an peer 1 address 1 */ set_ats (&a1_ats[1], GNUNET_ATS_QUALITY_NET_DELAY, 20); GAS_mlp_address_update (mlp, addresses, &addr[0]); GNUNET_assert (mlp->addr_in_problem == 1); /* Update an peer 1 address 1 */ set_ats (&a1_ats[1], GNUNET_ATS_QUALITY_NET_DELAY, 10); GAS_mlp_address_update (mlp, addresses, &addr[0]); GNUNET_assert (mlp->addr_in_problem == 1); /* Update an peer 1 address 1 */ set_ats (&a1_ats[1], GNUNET_ATS_QUALITY_NET_DELAY, 10); GAS_mlp_address_update (mlp, addresses, &addr[0]); GNUNET_assert (mlp->addr_in_problem == 1); /* Update an peer 1 address 1 */ set_ats (&a1_ats[1], GNUNET_ATS_QUALITY_NET_DELAY, 30); GAS_mlp_address_update (mlp, addresses, &addr[0]); GNUNET_assert (mlp->addr_in_problem == 1); GNUNET_assert (GNUNET_OK == GAS_mlp_solve_problem(mlp, &ctx)); GNUNET_assert (GNUNET_OK == ctx.lp_result); GNUNET_assert (GNUNET_OK == ctx.mlp_result); res[0] = GAS_mlp_get_preferred_address(mlp, addresses, &p[0]); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Preferred address `%s' outbound bandwidth: %u Bps\n",res[0]->address->plugin, res[0]->bandwidth_out); GNUNET_free (res[0]); /* Delete an address */ GNUNET_CONTAINER_multihashmap_remove (addresses, &addr[0].peer.hashPubKey, &addr[0]); GAS_mlp_address_delete (mlp, addresses, &addr[0]); GNUNET_assert (mlp->addr_in_problem == 0); GAS_mlp_done (mlp); GNUNET_free (addr[0].plugin); GNUNET_CONTAINER_multihashmap_destroy (addresses); GNUNET_STATISTICS_destroy(stats, GNUNET_NO); ret = 0; return; }
static void check (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { unsigned int c = 0; unsigned int c2 = 0; unsigned int ca = 0; int update = GNUNET_NO; int range = GNUNET_NO; int res; #if !HAVE_LIBGLPK GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "GLPK not installed!"); ret = 1; return; #endif GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Setting up %u peers with %u addresses per peer\n", peers, addresses); mlp = GAS_mlp_init (cfg, NULL, MLP_MAX_EXEC_DURATION, MLP_MAX_ITERATIONS); if (NULL == mlp) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to init MLP\n"); ret = 1; if (GNUNET_SCHEDULER_NO_TASK != shutdown_task) GNUNET_SCHEDULER_cancel(shutdown_task); shutdown_task = GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); } if (peers == 0) peers = DEF_PEERS; if (addresses == 0) addresses = DEF_ADDRESSES_PER_PEER; p = GNUNET_malloc (peers * sizeof (struct ATS_Peer)); a = GNUNET_malloc (peers * addresses * sizeof (struct ATS_Address)); amap = GNUNET_CONTAINER_multihashmap_create(addresses * peers, GNUNET_NO); mlp->auto_solve = GNUNET_NO; if (start == 0) start = 0; if (end == 0) end = -1; if ((start != -1) && (end != -1)) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Solving problem starting from %u to %u\n", start , end); range = GNUNET_YES; } else GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Solving problem for %u peers\n", peers); if ((update_percentage >= 0) && (update_percentage <= 100)) { update = GNUNET_YES; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Benchmarking with existing presolution and %u%% updated addresses\n", update_percentage); } else if ((update_percentage > 100) && (update_percentage != UINT_MAX)) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Invalid percentage: %u\n", update_percentage); ret = 1; return; } for (c=0; c < peers; c++) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Setting up peer %u\n", c); GNUNET_CRYPTO_hash_create_random(GNUNET_CRYPTO_QUALITY_NONCE, &p[c].id.hashPubKey); for (c2=0; c2 < addresses; c2++) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Setting up address %u for peer %u\n", c2, c); /* Setting required information */ a[ca].mlp_information = NULL; a[ca].prev = NULL; a[ca].next = NULL; /* Setting address */ a[ca].peer = p[c].id; a[ca].plugin = GNUNET_strdup("test"); a[ca].atsp_network_type = GNUNET_ATS_NET_LOOPBACK; a[ca].ats = GNUNET_malloc (DEF_ATS_VALUES * sizeof (struct GNUNET_ATS_Information)); a[ca].ats[0].type = GNUNET_ATS_QUALITY_NET_DELAY; a[ca].ats[0].value = GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_WEAK, DEF_ATS_MAX_DELAY); a[ca].ats[1].type = GNUNET_ATS_QUALITY_NET_DISTANCE; a[ca].ats[1].value = GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_WEAK, DEF_ATS_MAX_DISTANCE); a[ca].ats_count = 2; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Setting up address %u\n", ca); GNUNET_CONTAINER_multihashmap_put (amap, &a[ca].peer.hashPubKey, &a[ca], GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); GAS_mlp_address_update(mlp, amap, &a[ca]); ca++; } GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Problem contains %u peers and %u adresses\n", mlp->c_p, mlp->addr_in_problem); if (((GNUNET_YES == range) && (((start >= 0) && ((c+1) >= start)) && (c <= end))) || ((c+1) == peers)) { GNUNET_assert ((c+1) == mlp->c_p); GNUNET_assert ((c+1) * addresses == mlp->addr_in_problem); /* Solving the problem */ struct GAS_MLP_SolutionContext ctx; res = GAS_mlp_solve_problem(mlp, &ctx); if (GNUNET_NO == update) { if (GNUNET_OK == res) { GNUNET_assert (GNUNET_OK == ctx.lp_result); GNUNET_assert (GNUNET_OK == ctx.mlp_result); if (GNUNET_YES == numeric) printf ("%u;%u;%llu;%llu\n",mlp->c_p, mlp->addr_in_problem, (unsigned long long) ctx.lp_duration.rel_value, (unsigned long long) ctx.mlp_duration.rel_value); else GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Problem solved for %u peers with %u address successfully (LP: %llu ms / MLP: %llu ms)\n", mlp->c_p, mlp->addr_in_problem, ctx.lp_duration.rel_value, ctx.mlp_duration.rel_value); } else GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Solving problem with %u peers and %u addresses failed\n", c, c2); } else { struct GAS_MLP_SolutionContext uctx; /* Update addresses */ update_addresses (a, (c+1) * c2, update_percentage); /* Solve again */ res = GAS_mlp_solve_problem(mlp, &uctx); if (GNUNET_OK == res) { GNUNET_assert (GNUNET_OK == uctx.lp_result); GNUNET_assert (GNUNET_OK == uctx.mlp_result); if (GNUNET_YES == numeric) printf ("%u;%u;%llu;%llu;%llu;%llu\n",mlp->c_p, mlp->addr_in_problem, (unsigned long long) ctx.lp_duration.rel_value, (unsigned long long) ctx.mlp_duration.rel_value, (unsigned long long) uctx.lp_duration.rel_value, (unsigned long long) uctx.mlp_duration.rel_value); else GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Updated problem solved for %u peers with %u address successfully (Initial: LP/MLP: %llu/%llu ms, Update: %llu/%llu ms)\n", mlp->c_p, mlp->addr_in_problem, (unsigned long long) ctx.lp_duration.rel_value, (unsigned long long) ctx.mlp_duration.rel_value, (unsigned long long) uctx.lp_duration.rel_value, (unsigned long long) uctx.mlp_duration.rel_value); } else GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Solving updated problem with %u peers and %u addresses failed\n", c, c2); } } } if (GNUNET_SCHEDULER_NO_TASK != shutdown_task) GNUNET_SCHEDULER_cancel(shutdown_task); shutdown_task = GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); }
static void update_addresses (struct ATS_Address * a, unsigned int addrs, unsigned int percentage) { if (percentage == 0) return; unsigned int ua = (addrs) * ((float) percentage / 100); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Updating %u of %u addresses per peer\n", ua, addrs); unsigned int updated[addrs]; unsigned int u_types[DEF_ATS_VALUES]; unsigned int updates = 0; unsigned int u_type = 0; unsigned int u_val = 0; unsigned int cur = 0; u_types[0] = 0; u_types[1] = 0; for (cur = 0; cur < addrs; cur ++) { updated[cur] = 0; } cur = 0; while (updates < ua) { cur = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, addrs); if (0 == updated[cur]) { u_type = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, DEF_ATS_VALUES); switch (u_type) { case 0: do { u_val = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, DEF_ATS_MAX_DELAY); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Updating DELAY from %u to %u\n",a[cur].ats[u_type].value, u_val); } while (a[cur].ats[u_type].value == u_val); break; case 1: do { u_val = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, DEF_ATS_MAX_DISTANCE); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Updating DISTANCE from %u to %u\n",a[cur].ats[u_type].value, u_val); } while (a[cur].ats[u_type].value == u_val); break; default: GNUNET_break (0); break; } u_types[u_type]++; a[cur].ats[u_type].value = u_val; updated[cur] = 1; GAS_mlp_address_update(mlp, amap, &a[cur]); updates++; } } GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Updated %u delay and %u distance values\n", u_types[0], u_types[1]); }
void GAS_addresses_update (const struct GNUNET_PeerIdentity *peer, const char *plugin_name, const void *plugin_addr, size_t plugin_addr_len, uint32_t session_id, const struct GNUNET_ATS_Information *atsi, uint32_t atsi_count) { struct ATS_Address *aa; struct ATS_Address *old; uint32_t i; if (GNUNET_NO == running) return; GNUNET_assert (NULL != addresses); aa = create_address (peer, plugin_name, plugin_addr, plugin_addr_len, session_id); aa->mlp_information = NULL; aa->ats = GNUNET_malloc (atsi_count * sizeof (struct GNUNET_ATS_Information)); aa->ats_count = atsi_count; memcpy (aa->ats, atsi, atsi_count * sizeof (struct GNUNET_ATS_Information)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Updating address for peer `%s' %u\n", GNUNET_i2s (peer), session_id); /* Get existing address or address with session == 0 */ old = find_address (peer, aa); if (old == NULL) { GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put (addresses, &peer->hashPubKey, aa, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)); #if DEBUG_ATS GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Added new address for peer `%s' %X\n", GNUNET_i2s (peer), aa); #endif old = aa; } else { #if DEBUG_ATS GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Updated existing address for peer `%s' %p old session %u new session %u\n", GNUNET_i2s (peer), old, old->session_id, session_id); #endif GNUNET_free_non_null (old->ats); old->session_id = session_id; old->ats = NULL; old->ats_count = 0; old->ats = aa->ats; old->ats_count = aa->ats_count; GNUNET_free (aa->plugin); GNUNET_free (aa); } for (i = 0; i < atsi_count; i++) switch (ntohl (atsi[i].type)) { case GNUNET_ATS_UTILIZATION_UP: old->atsp_utilization_out.value__ = atsi[i].value; break; case GNUNET_ATS_UTILIZATION_DOWN: old->atsp_utilization_in.value__ = atsi[i].value; break; case GNUNET_ATS_QUALITY_NET_DELAY: old->atsp_latency.rel_value = ntohl (atsi[i].value); break; case GNUNET_ATS_QUALITY_NET_DISTANCE: old->atsp_distance = ntohl (atsi[i].value); break; case GNUNET_ATS_COST_WAN: old->atsp_cost_wan = ntohl (atsi[i].value); break; case GNUNET_ATS_COST_LAN: old->atsp_cost_lan = ntohl (atsi[i].value); break; case GNUNET_ATS_COST_WLAN: old->atsp_cost_wlan = ntohl (atsi[i].value); break; case GNUNET_ATS_NETWORK_TYPE: old->atsp_network_type = ntohl (atsi[i].value); break; default: GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Received unsupported ATS type %u\n", ntohl (atsi[i].type)); GNUNET_break (0); break; } #if HAVE_LIBGLPK if (ats_mode == MLP) GAS_mlp_address_update (mlp, addresses, old); #endif }
void GAS_addresses_update (const struct GNUNET_PeerIdentity *peer, const char *plugin_name, const void *plugin_addr, size_t plugin_addr_len, uint32_t session_id, const struct GNUNET_ATS_Information *atsi, uint32_t atsi_count) { struct ATS_Address *old; uint32_t i; if (GNUNET_NO == running) return; GNUNET_assert (NULL != addresses); /* Get existing address */ old = lookup_address (peer, plugin_name, plugin_addr, plugin_addr_len, session_id, atsi, atsi_count); if (old == NULL) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Tried to update unknown address for peer `%s' `%s' session id %u\n", GNUNET_i2s (peer), plugin_name, session_id); GNUNET_break (0); return; } for (i = 0; i < atsi_count; i++) switch (ntohl (atsi[i].type)) { case GNUNET_ATS_UTILIZATION_UP: old->atsp_utilization_out.value__ = atsi[i].value; break; case GNUNET_ATS_UTILIZATION_DOWN: old->atsp_utilization_in.value__ = atsi[i].value; break; case GNUNET_ATS_QUALITY_NET_DELAY: old->atsp_latency.rel_value = ntohl (atsi[i].value); break; case GNUNET_ATS_QUALITY_NET_DISTANCE: old->atsp_distance = ntohl (atsi[i].value); break; case GNUNET_ATS_COST_WAN: old->atsp_cost_wan = ntohl (atsi[i].value); break; case GNUNET_ATS_COST_LAN: old->atsp_cost_lan = ntohl (atsi[i].value); break; case GNUNET_ATS_COST_WLAN: old->atsp_cost_wlan = ntohl (atsi[i].value); break; case GNUNET_ATS_NETWORK_TYPE: old->atsp_network_type = ntohl (atsi[i].value); break; default: GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Received unsupported ATS type %u\n", ntohl (atsi[i].type)); GNUNET_break (0); break; } #if HAVE_LIBGLPK if (ats_mode == MLP) GAS_mlp_address_update (mlp, addresses, old); #endif }