gnunet_dht_profiler.c 39 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460
  1. /*
  2. This file is part of GNUnet.
  3. (C) 2014 Christian Grothoff (and other contributing authors)
  4. GNUnet is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published
  6. by the Free Software Foundation; either version 3, or (at your
  7. option) any later version.
  8. GNUnet is distributed in the hope that it will be useful, but
  9. WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with GNUnet; see the file COPYING. If not, write to the
  14. Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  15. Boston, MA 02111-1307, USA.
  16. */
  17. /**
  18. * @file dht/gnunet_dht_profiler.c
  19. * @brief Profiler for GNUnet DHT
  20. * @author Sree Harsha Totakura <sreeharsha@totakura.in>
  21. */
  22. #include "platform.h"
  23. #include "gnunet_util_lib.h"
  24. #include "gnunet_testbed_service.h"
  25. #include "gnunet_dht_service.h"
  26. #define INFO(...) \
  27. GNUNET_log (GNUNET_ERROR_TYPE_INFO, __VA_ARGS__)
  28. #define DEBUG(...) \
  29. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__)
  30. /**
  31. * Number of peers which should perform a PUT out of 100 peers
  32. */
  33. #define PUT_PROBABILITY 50
  34. #if ENABLE_MALICIOUS
  35. /**
  36. * Number of peers which should act as malicious peers
  37. */
  38. #define MALICIOUS_PROBABILITY 20
  39. /**
  40. * Context for a peer which should act maliciously.
  41. */
  42. struct MaliciousContext;
  43. #endif
  44. /**
  45. * Configuration
  46. */
  47. static struct GNUNET_CONFIGURATION_Handle *cfg;
  48. /**
  49. * Name of the file with the hosts to run the test over
  50. */
  51. static char *hosts_file;
  52. /**
  53. * Context for a peer which actively does DHT PUT/GET
  54. */
  55. struct ActiveContext;
  56. /**
  57. * Context to hold data of peer
  58. */
  59. struct Context
  60. {
  61. /**
  62. * The testbed peer this context belongs to
  63. */
  64. struct GNUNET_TESTBED_Peer *peer;
  65. /**
  66. * Testbed operation acting on this peer
  67. */
  68. struct GNUNET_TESTBED_Operation *op;
  69. /**
  70. * Active context; NULL if this peer is not an active peer
  71. */
  72. struct ActiveContext *ac;
  73. #if ENABLE_MALICIOUS
  74. /**
  75. * Malicious context; NULL if this peer is NOT malicious.
  76. */
  77. struct MaliciousContext *mc;
  78. #endif
  79. };
  80. #if ENABLE_MALICIOUS
  81. /**
  82. * Context for a peer which should act maliciously.
  83. */
  84. struct MaliciousContext
  85. {
  86. /**
  87. * The linked peer context
  88. */
  89. struct Context *ctx;
  90. /**
  91. * Handler to the DHT service
  92. */
  93. struct GNUNET_DHT_Handle *dht;
  94. /**
  95. * Handler to malicious api
  96. */
  97. struct GNUNET_DHT_ActMaliciousHandle *dht_malicious;
  98. };
  99. /**
  100. * List of all the malicious peers contexts.
  101. */
  102. struct Context **malicious_peer_contexts = NULL;
  103. /**
  104. * Context for a peer which should act maliciously.
  105. */
  106. struct Malicious_Context
  107. {
  108. /**
  109. * The linked peer context
  110. */
  111. struct Context *ctx;
  112. /**
  113. * Handler to the DHT service
  114. */
  115. struct GNUNET_DHT_Handle *dht;
  116. };
  117. /**
  118. * Array of malicious peers.
  119. */
  120. static struct MaliciousContext *a_mc;
  121. /**
  122. * Number or malicious peers.
  123. */
  124. static unsigned int n_malicious;
  125. #endif
  126. /**
  127. * Context for a peer which actively does DHT PUT/GET
  128. */
  129. struct ActiveContext
  130. {
  131. /**
  132. * The linked peer context
  133. */
  134. struct Context *ctx;
  135. /**
  136. * Handler to the DHT service
  137. */
  138. struct GNUNET_DHT_Handle *dht;
  139. /**
  140. * The data used for do a PUT. Will be NULL if a PUT hasn't been performed yet
  141. */
  142. void *put_data;
  143. /**
  144. * The active context used for our DHT GET
  145. */
  146. struct ActiveContext *get_ac;
  147. /**
  148. * The put handle
  149. */
  150. struct GNUNET_DHT_PutHandle *dht_put;
  151. /**
  152. * The get handle
  153. */
  154. struct GNUNET_DHT_GetHandle *dht_get;
  155. /**
  156. * The hash of the @e put_data
  157. */
  158. struct GNUNET_HashCode hash;
  159. /**
  160. * Delay task
  161. */
  162. GNUNET_SCHEDULER_TaskIdentifier delay_task;
  163. /**
  164. * The size of the @e put_data
  165. */
  166. uint16_t put_data_size;
  167. /**
  168. * The number of peers currently doing GET on our data
  169. */
  170. uint16_t nrefs;
  171. };
  172. /**
  173. * An array of contexts. The size of this array should be equal to @a num_peers
  174. */
  175. static struct Context *a_ctx;
  176. /**
  177. * Array of active peers
  178. */
  179. static struct ActiveContext *a_ac;
  180. /**
  181. * The delay between rounds for collecting statistics
  182. */
  183. static struct GNUNET_TIME_Relative delay_stats;
  184. /**
  185. * The delay to start puts.
  186. */
  187. static struct GNUNET_TIME_Relative delay_put;
  188. /**
  189. * The delay to start puts.
  190. */
  191. static struct GNUNET_TIME_Relative delay_get;
  192. /**
  193. * The timeout for GET and PUT
  194. */
  195. static struct GNUNET_TIME_Relative timeout;
  196. /**
  197. * Number of peers
  198. */
  199. static unsigned int num_peers;
  200. /**
  201. * Number of active peers
  202. */
  203. static unsigned int n_active;
  204. /**
  205. * Number of DHT service connections we currently have
  206. */
  207. static unsigned int n_dht;
  208. /**
  209. * Number of DHT PUTs made
  210. */
  211. static unsigned int n_puts;
  212. /**
  213. * Number of DHT PUTs succeeded
  214. */
  215. static unsigned int n_puts_ok;
  216. /**
  217. * Number of DHT PUTs failed
  218. */
  219. static unsigned int n_puts_fail;
  220. /**
  221. * Number of DHT GETs made
  222. */
  223. static unsigned int n_gets;
  224. /**
  225. * Number of DHT GETs succeeded
  226. */
  227. static unsigned int n_gets_ok;
  228. /**
  229. * Number of DHT GETs succeeded
  230. */
  231. static unsigned int n_gets_fail;
  232. /**
  233. * Replication degree
  234. */
  235. static unsigned int replication;
  236. /**
  237. * Number of times we try to find the successor circle formation
  238. */
  239. static unsigned int max_searches;
  240. /**
  241. * Testbed Operation (to get stats).
  242. */
  243. static struct GNUNET_TESTBED_Operation *bandwidth_stats_op;
  244. /**
  245. * To get successor stats.
  246. */
  247. static struct GNUNET_TESTBED_Operation *successor_stats_op;
  248. /**
  249. * Testbed peer handles.
  250. */
  251. static struct GNUNET_TESTBED_Peer **testbed_handles;
  252. /**
  253. * Total number of messages sent by peer.
  254. */
  255. static uint64_t outgoing_bandwidth;
  256. /**
  257. * Total number of messages received by peer.
  258. */
  259. static uint64_t incoming_bandwidth;
  260. /**
  261. * Average number of hops taken to do put.
  262. */
  263. static double average_put_path_length;
  264. /**
  265. * Average number of hops taken to do get.
  266. */
  267. static double average_get_path_length;
  268. /**
  269. * Total put path length across all peers.
  270. */
  271. static unsigned int total_put_path_length;
  272. /**
  273. * Total get path length across all peers.
  274. */
  275. static unsigned int total_get_path_length;
  276. /**
  277. * Hashmap to store pair of peer and its corresponding successor.
  278. */
  279. static struct GNUNET_CONTAINER_MultiHashMap *successor_peer_hashmap;
  280. /**
  281. * Key to start the lookup on successor_peer_hashmap.
  282. */
  283. static struct GNUNET_HashCode *start_key;
  284. /**
  285. * Flag used to get the start_key.
  286. */
  287. static int flag = 0;
  288. /**
  289. * Task to collect peer and its current successor statistics.
  290. */
  291. static GNUNET_SCHEDULER_TaskIdentifier successor_stats_task;
  292. /**
  293. * Closure for successor_stats_task.
  294. */
  295. struct Collect_Stat_Context
  296. {
  297. /**
  298. * Current Peer Context.
  299. */
  300. struct Context *service_connect_ctx;
  301. /**
  302. * Testbed operation acting on this peer
  303. */
  304. struct GNUNET_TESTBED_Operation *op;
  305. };
  306. /**
  307. * List of all the peers contexts.
  308. */
  309. struct Context **peer_contexts = NULL;
  310. /**
  311. * Counter to keep track of peers added to peer_context lists.
  312. */
  313. static int peers_started = 0;
  314. /**
  315. * Should we do a PUT (mode = 0) or GET (mode = 1);
  316. */
  317. static enum
  318. {
  319. MODE_PUT = 0,
  320. MODE_GET = 1
  321. } mode;
  322. /**
  323. * Are we shutting down
  324. */
  325. static int in_shutdown = 0;
  326. /**
  327. * Total number of times to check if circle is formed or not.
  328. */
  329. static unsigned int tries;
  330. /**
  331. * Task that collects successor statistics from all the peers.
  332. * @param cls
  333. * @param tc
  334. */
  335. static void
  336. collect_stats (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
  337. /**
  338. * Connect to DHT services of active peers
  339. */
  340. static void
  341. start_profiling();
  342. /**
  343. * Shutdown task. Cleanup all resources and operations.
  344. *
  345. * @param cls NULL
  346. * @param tc scheduler task context
  347. */
  348. static void
  349. do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
  350. {
  351. struct ActiveContext *ac;
  352. unsigned int cnt;
  353. in_shutdown = GNUNET_YES;
  354. if (NULL != a_ctx)
  355. {
  356. for (cnt=0; cnt < num_peers; cnt++)
  357. {
  358. /* Cleanup active context if this peer is an active peer */
  359. ac = a_ctx[cnt].ac;
  360. if (NULL != ac)
  361. {
  362. if (GNUNET_SCHEDULER_NO_TASK != ac->delay_task)
  363. GNUNET_SCHEDULER_cancel (ac->delay_task);
  364. if (NULL != ac->put_data)
  365. GNUNET_free (ac->put_data);
  366. if (NULL != ac->dht_put)
  367. GNUNET_DHT_put_cancel (ac->dht_put);
  368. if (NULL != ac->dht_get)
  369. GNUNET_DHT_get_stop (ac->dht_get);
  370. }
  371. /* Cleanup testbed operation handle at the last as this operation may
  372. contain service connection to DHT */
  373. if (NULL != a_ctx[cnt].op)
  374. GNUNET_TESTBED_operation_done (a_ctx[cnt].op);
  375. }
  376. GNUNET_free (a_ctx);
  377. a_ctx = NULL;
  378. }
  379. //FIXME: Should we collect stats only for put/get not for other messages.
  380. if(NULL != bandwidth_stats_op)
  381. GNUNET_TESTBED_operation_done (bandwidth_stats_op);
  382. bandwidth_stats_op = NULL;
  383. GNUNET_free_non_null (a_ac);
  384. }
  385. /**
  386. * Stats callback. Finish the stats testbed operation and when all stats have
  387. * been iterated, shutdown the test.
  388. *
  389. * @param cls closure
  390. * @param op the operation that has been finished
  391. * @param emsg error message in case the operation has failed; will be NULL if
  392. * operation has executed successfully.
  393. */
  394. static void
  395. bandwidth_stats_cont (void *cls,
  396. struct GNUNET_TESTBED_Operation *op,
  397. const char *emsg)
  398. {
  399. INFO ("# Outgoing bandwidth: %u\n", outgoing_bandwidth);
  400. INFO ("# Incoming bandwidth: %u\n", incoming_bandwidth);
  401. GNUNET_SCHEDULER_shutdown ();
  402. }
  403. /**
  404. * Process statistic values.
  405. *
  406. * @param cls closure
  407. * @param peer the peer the statistic belong to
  408. * @param subsystem name of subsystem that created the statistic
  409. * @param name the name of the datum
  410. * @param value the current value
  411. * @param is_persistent GNUNET_YES if the value is persistent, GNUNET_NO if not
  412. * @return GNUNET_OK to continue, GNUNET_SYSERR to abort iteration
  413. */
  414. static int
  415. bandwidth_stats_iterator (void *cls,
  416. const struct GNUNET_TESTBED_Peer *peer,
  417. const char *subsystem,
  418. const char *name,
  419. uint64_t value,
  420. int is_persistent)
  421. {
  422. static const char *s_sent = "# Bytes transmitted to other peers";
  423. static const char *s_recv = "# Bytes received from other peers";
  424. if (0 == strncmp (s_sent, name, strlen (s_sent)))
  425. outgoing_bandwidth = outgoing_bandwidth + value;
  426. else if (0 == strncmp(s_recv, name, strlen (s_recv)))
  427. incoming_bandwidth = incoming_bandwidth + value;
  428. return GNUNET_OK;
  429. }
  430. static void
  431. summarize ()
  432. {
  433. INFO ("# PUTS made: %u\n", n_puts);
  434. INFO ("# PUTS succeeded: %u\n", n_puts_ok);
  435. INFO ("# PUTS failed: %u\n", n_puts_fail);
  436. INFO ("# GETS made: %u\n", n_gets);
  437. INFO ("# GETS succeeded: %u\n", n_gets_ok);
  438. INFO ("# GETS failed: %u\n", n_gets_fail);
  439. INFO ("# average_put_path_length: %f\n", average_put_path_length);
  440. INFO ("# average_get_path_length: %f\n", average_get_path_length);
  441. if (NULL == testbed_handles)
  442. {
  443. INFO ("No peers found\n");
  444. return;
  445. }
  446. /* Collect Stats*/
  447. bandwidth_stats_op = GNUNET_TESTBED_get_statistics (n_active, testbed_handles,
  448. "dht", NULL,
  449. bandwidth_stats_iterator,
  450. bandwidth_stats_cont, NULL);
  451. }
  452. /**
  453. * Task to cancel DHT GET.
  454. *
  455. * @param cls NULL
  456. * @param tc scheduler task context
  457. */
  458. static void
  459. cancel_get (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
  460. {
  461. struct ActiveContext *ac = cls;
  462. struct Context *ctx = ac->ctx;
  463. ac->delay_task = GNUNET_SCHEDULER_NO_TASK;
  464. GNUNET_assert (NULL != ac->dht_get);
  465. GNUNET_DHT_get_stop (ac->dht_get);
  466. ac->dht_get = NULL;
  467. n_gets_fail++;
  468. GNUNET_assert (NULL != ctx->op);
  469. GNUNET_TESTBED_operation_done (ctx->op);
  470. ctx->op = NULL;
  471. /* If profiling is complete, summarize */
  472. if (n_active == n_gets_fail + n_gets_ok)
  473. {
  474. average_put_path_length = (double)total_put_path_length/(double)n_active;
  475. average_get_path_length = (double)total_get_path_length/(double )n_gets_ok;
  476. summarize ();
  477. }
  478. }
  479. /**
  480. * Iterator called on each result obtained for a DHT
  481. * operation that expects a reply
  482. *
  483. * @param cls closure
  484. * @param exp when will this value expire
  485. * @param key key of the result
  486. * @param get_path peers on reply path (or NULL if not recorded)
  487. * [0] = datastore's first neighbor, [length - 1] = local peer
  488. * @param get_path_length number of entries in @a get_path
  489. * @param put_path peers on the PUT path (or NULL if not recorded)
  490. * [0] = origin, [length - 1] = datastore
  491. * @param put_path_length number of entries in @a put_path
  492. * @param type type of the result
  493. * @param size number of bytes in @a data
  494. * @param data pointer to the result data
  495. */
  496. static void
  497. get_iter (void *cls,
  498. struct GNUNET_TIME_Absolute exp,
  499. const struct GNUNET_HashCode *key,
  500. const struct GNUNET_PeerIdentity *get_path,
  501. unsigned int get_path_length,
  502. const struct GNUNET_PeerIdentity *put_path,
  503. unsigned int put_path_length,
  504. enum GNUNET_BLOCK_Type type,
  505. size_t size, const void *data)
  506. {
  507. struct ActiveContext *ac = cls;
  508. struct ActiveContext *get_ac = ac->get_ac;
  509. struct Context *ctx = ac->ctx;
  510. /* Check the keys of put and get match or not. */
  511. GNUNET_assert (0 == memcmp (key, &get_ac->hash, sizeof (struct GNUNET_HashCode)));
  512. /* we found the data we are looking for */
  513. DEBUG ("We found a GET request; %u remaining\n", n_gets - (n_gets_fail + n_gets_ok)); //FIXME: It always prints 1.
  514. n_gets_ok++;
  515. get_ac->nrefs--;
  516. GNUNET_DHT_get_stop (ac->dht_get);
  517. ac->dht_get = NULL;
  518. if (ac->delay_task != GNUNET_SCHEDULER_NO_TASK)
  519. GNUNET_SCHEDULER_cancel (ac->delay_task);
  520. ac->delay_task = GNUNET_SCHEDULER_NO_TASK;
  521. GNUNET_assert (NULL != ctx->op);
  522. GNUNET_TESTBED_operation_done (ctx->op);
  523. ctx->op = NULL;
  524. total_put_path_length = total_put_path_length + (double)put_path_length;
  525. total_get_path_length = total_get_path_length + (double)get_path_length;
  526. DEBUG ("total_put_path_length = %f,put_path \n",total_put_path_length);
  527. /* Summarize if profiling is complete */
  528. if (n_active == n_gets_fail + n_gets_ok)
  529. {
  530. average_put_path_length = (double)total_put_path_length/(double)n_active;
  531. average_get_path_length = (double)total_get_path_length/(double )n_gets_ok;
  532. summarize ();
  533. }
  534. }
  535. /**
  536. * Task to do DHT GETs
  537. *
  538. * @param cls the active context
  539. * @param tc the scheduler task context
  540. */
  541. static void
  542. delayed_get (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
  543. {
  544. struct ActiveContext *ac = cls;
  545. struct ActiveContext *get_ac;
  546. unsigned int r;
  547. ac->delay_task = GNUNET_SCHEDULER_NO_TASK;
  548. get_ac = NULL;
  549. while (1)
  550. {
  551. r = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, n_active);
  552. get_ac = &a_ac[r];
  553. if (NULL != get_ac->put_data)
  554. break;
  555. }
  556. get_ac->nrefs++;
  557. ac->get_ac = get_ac;
  558. DEBUG ("GET_REQUEST_START key %s \n", GNUNET_h2s((struct GNUNET_HashCode *)ac->put_data));
  559. ac->dht_get = GNUNET_DHT_get_start (ac->dht,
  560. GNUNET_BLOCK_TYPE_TEST,
  561. &get_ac->hash,
  562. 1, /* replication level */
  563. GNUNET_DHT_RO_NONE,
  564. NULL, 0, /* extended query and size */
  565. get_iter, ac); /* GET iterator and closure
  566. */
  567. n_gets++;
  568. /* schedule the timeout task for GET */
  569. ac->delay_task = GNUNET_SCHEDULER_add_delayed (timeout, &cancel_get, ac);
  570. }
  571. /**
  572. * Task to teardown the dht connection. We do it as a task because calling
  573. * GNUNET_DHT_disconnect() from put_continutation_callback seems illegal (the
  574. * put_continuation_callback() is getting called again synchronously). Also,
  575. * only free the operation when we are not shutting down; the shutdown task will
  576. * clear the operation during shutdown.
  577. *
  578. * @param cls the context
  579. * @return tc scheduler task context.
  580. */
  581. static void
  582. teardown_dht_connection (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
  583. {
  584. struct Context *ctx = cls;
  585. struct GNUNET_TESTBED_Operation *op;
  586. if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason))
  587. return;
  588. GNUNET_assert (NULL != ctx);
  589. GNUNET_assert (NULL != (op = ctx->op));
  590. ctx->op = NULL;
  591. GNUNET_TESTBED_operation_done (op);
  592. }
  593. /**
  594. * Queue up a delayed task for doing DHT GET
  595. *
  596. * @param cls the active context
  597. * @param success #GNUNET_OK if the PUT was transmitted,
  598. * #GNUNET_NO on timeout,
  599. * #GNUNET_SYSERR on disconnect from service
  600. * after the PUT message was transmitted
  601. * (so we don't know if it was received or not)
  602. */
  603. static void
  604. put_cont (void *cls, int success)
  605. {
  606. struct ActiveContext *ac = cls;
  607. struct Context *ctx = ac->ctx;
  608. ac->dht_put = NULL;
  609. if (success)
  610. n_puts_ok++;
  611. else
  612. n_puts_fail++;
  613. GNUNET_assert (NULL != ctx);
  614. (void) GNUNET_SCHEDULER_add_now (&teardown_dht_connection, ctx);
  615. }
  616. /**
  617. * Task to do DHT PUTS
  618. *
  619. * @param cls the active context
  620. * @param tc the scheduler task context
  621. */
  622. static void
  623. delayed_put (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
  624. {
  625. struct ActiveContext *ac = cls;
  626. ac->delay_task = GNUNET_SCHEDULER_NO_TASK;
  627. /* Generate and DHT PUT some random data */
  628. ac->put_data_size = 16; /* minimum */
  629. ac->put_data_size += GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
  630. (63*1024));
  631. ac->put_data = GNUNET_malloc (ac->put_data_size);
  632. GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
  633. ac->put_data, ac->put_data_size);
  634. GNUNET_CRYPTO_hash (ac->put_data, ac->put_data_size, &ac->hash);
  635. DEBUG ("PUT_REQUEST_START key %s \n", GNUNET_h2s((struct GNUNET_HashCode *)ac->put_data));
  636. ac->dht_put = GNUNET_DHT_put (ac->dht, &ac->hash,
  637. replication,
  638. GNUNET_DHT_RO_RECORD_ROUTE,
  639. GNUNET_BLOCK_TYPE_TEST,
  640. ac->put_data_size,
  641. ac->put_data,
  642. GNUNET_TIME_UNIT_FOREVER_ABS, /* expiration time */
  643. timeout, /* PUT timeout */
  644. put_cont, ac); /* continuation and its closure */
  645. n_puts++;
  646. }
  647. /**
  648. * Connection to DHT has been established. Call the delay task.
  649. *
  650. * @param cls the active context
  651. * @param op the operation that has been finished
  652. * @param ca_result the service handle returned from GNUNET_TESTBED_ConnectAdapter()
  653. * @param emsg error message in case the operation has failed; will be NULL if
  654. * operation has executed successfully.
  655. */
  656. static void
  657. dht_connected (void *cls,
  658. struct GNUNET_TESTBED_Operation *op,
  659. void *ca_result,
  660. const char *emsg)
  661. {
  662. struct ActiveContext *ac = cls;
  663. struct Context *ctx = ac->ctx;
  664. GNUNET_assert (NULL != ctx); //FIXME: Fails
  665. GNUNET_assert (NULL != ctx->op);
  666. GNUNET_assert (ctx->op == op);
  667. ac->dht = (struct GNUNET_DHT_Handle *) ca_result;
  668. if (NULL != emsg)
  669. {
  670. GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Connection to DHT service failed: %s\n", emsg);
  671. GNUNET_TESTBED_operation_done (ctx->op); /* Calls dht_disconnect() */
  672. ctx->op = NULL;
  673. return;
  674. }
  675. switch (mode)
  676. {
  677. case MODE_PUT:
  678. {
  679. struct GNUNET_TIME_Relative peer_delay_put;
  680. peer_delay_put.rel_value_us =
  681. GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
  682. delay_put.rel_value_us);
  683. ac->delay_task = GNUNET_SCHEDULER_add_delayed (peer_delay_put, &delayed_put, ac);
  684. break;
  685. }
  686. case MODE_GET:
  687. {
  688. struct GNUNET_TIME_Relative peer_delay_get;
  689. peer_delay_get.rel_value_us =
  690. delay_get.rel_value_us +
  691. GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
  692. delay_get.rel_value_us);
  693. ac->delay_task = GNUNET_SCHEDULER_add_delayed (peer_delay_get, &delayed_get, ac);
  694. break;
  695. }
  696. }
  697. }
  698. /**
  699. * Connect to DHT service and return the DHT client handler
  700. *
  701. * @param cls the active context
  702. * @param cfg configuration of the peer to connect to; will be available until
  703. * GNUNET_TESTBED_operation_done() is called on the operation returned
  704. * from GNUNET_TESTBED_service_connect()
  705. * @return service handle to return in 'op_result', NULL on error
  706. */
  707. static void *
  708. dht_connect (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg)
  709. {
  710. n_dht++;
  711. return GNUNET_DHT_connect (cfg, 10);
  712. }
  713. /**
  714. * Adapter function called to destroy a connection to
  715. * a service.
  716. *
  717. * @param cls the active context
  718. * @param op_result service handle returned from the connect adapter
  719. */
  720. static void
  721. dht_disconnect (void *cls, void *op_result)
  722. {
  723. struct ActiveContext *ac = cls;
  724. GNUNET_assert (NULL != ac->dht);
  725. GNUNET_assert (ac->dht == op_result);
  726. GNUNET_DHT_disconnect (ac->dht);
  727. ac->dht = NULL;
  728. n_dht--;
  729. if (0 != n_dht)
  730. return;
  731. if (GNUNET_YES == in_shutdown)
  732. return;
  733. switch (mode)
  734. {
  735. case MODE_PUT:
  736. if ((n_puts_ok + n_puts_fail) != n_active)
  737. return;
  738. /* Start GETs if all PUTs have been made */
  739. mode = MODE_GET;
  740. //(void) GNUNET_SCHEDULER_add_now (&call_start_profiling, NULL);
  741. start_profiling ();
  742. return;
  743. case MODE_GET:
  744. if ((n_gets_ok + n_gets_fail) != n_active)
  745. return;
  746. break;
  747. }
  748. }
  749. /**
  750. * Connect to DHT services of active peers
  751. */
  752. static void
  753. start_profiling()
  754. {
  755. struct Context *ctx;
  756. unsigned int i;
  757. DEBUG("GNUNET_TESTBED_service_connect \n");
  758. GNUNET_break (GNUNET_YES != in_shutdown);
  759. for(i = 0; i < n_active; i++)
  760. {
  761. struct ActiveContext *ac = &a_ac[i];
  762. GNUNET_assert (NULL != (ctx = ac->ctx));
  763. GNUNET_assert (NULL == ctx->op);
  764. ctx->op =
  765. GNUNET_TESTBED_service_connect (ctx,
  766. ctx->peer,
  767. "dht",
  768. &dht_connected, ac,
  769. &dht_connect,
  770. &dht_disconnect,
  771. ac);
  772. }
  773. }
  774. #if ENABLE_MALICIOUS
  775. /**
  776. * Count of total number of malicious peers.
  777. */
  778. static unsigned int count_malicious;
  779. /**
  780. * Continuation of GNUNET_DHT_act_malicious
  781. * @param cls Malicious context
  782. * @param success #GNUNET_OK if the ACT_MALICIOUS was transmitted,
  783. * #GNUNET_NO on timeout,
  784. * #GNUNET_SYSERR on disconnect from service
  785. * after the ACT_MALICIOUS message was transmitted
  786. * (so we don't know if it was received or not)
  787. */
  788. static void
  789. act_malicious_cont (void *cls, int success)
  790. {
  791. struct MaliciousContext *mc = cls;
  792. struct Context *ctx = mc->ctx;
  793. GNUNET_TESTBED_operation_done (ctx->op);
  794. ctx->op = NULL;
  795. return;
  796. }
  797. /**
  798. * Call malicious API for all the malicious peers.
  799. * @param cls the malicious context.
  800. * @param op the operation that has been finished
  801. * @param ca_result the service handle returned from GNUNET_TESTBED_ConnectAdapter()
  802. * @param emsg error message in case the operation has failed; will be NULL if
  803. * operation has executed successfully.
  804. */
  805. void
  806. dht_set_malicious(void *cls,
  807. struct GNUNET_TESTBED_Operation *op,
  808. void *ca_result,
  809. const char *emsg)
  810. {
  811. struct MaliciousContext *mc = cls;
  812. struct Context *ctx = mc->ctx;
  813. GNUNET_assert (NULL != ctx);
  814. GNUNET_assert (NULL != ctx->op);
  815. GNUNET_assert (ctx->op == op);
  816. mc->dht = (struct GNUNET_DHT_Handle *) ca_result;
  817. if (NULL != emsg)
  818. {
  819. GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Connection to DHT service failed: %s\n", emsg);
  820. GNUNET_TESTBED_operation_done (ctx->op); /* Calls dht_disconnect_malicious() */
  821. ctx->op = NULL;
  822. return;
  823. }
  824. mc->dht_malicious = GNUNET_DHT_act_malicious(mc->dht, 1, act_malicious_cont, mc);
  825. }
  826. /**
  827. * Adapter function called to destroy a connection to
  828. * a service.
  829. *
  830. * @param cls the active context
  831. * @param op_result service handle returned from the connect adapter
  832. */
  833. static void
  834. dht_disconnect_malicious (void *cls, void *op_result)
  835. {
  836. struct MaliciousContext *mc = cls;
  837. count_malicious++;
  838. GNUNET_assert (NULL != mc->dht);
  839. GNUNET_assert (mc->dht == op_result);
  840. GNUNET_DHT_disconnect (mc->dht);
  841. mc->dht = NULL;
  842. mc->ctx->op = NULL;
  843. n_dht--;
  844. if (0 != n_dht)
  845. return;
  846. if(n_malicious == count_malicious)
  847. {
  848. DEBUG("\n Call start_profiling()");
  849. start_profiling();
  850. }
  851. }
  852. /**
  853. * Set the malicious variable in peer malicious context.
  854. */
  855. static void
  856. set_malicious()
  857. {
  858. unsigned int i;
  859. DEBUG ("Setting %u peers malicious",n_malicious);
  860. for(i = 0; i < n_malicious; i++)
  861. {
  862. struct MaliciousContext *mc = &a_mc[i];
  863. mc->ctx->op =
  864. GNUNET_TESTBED_service_connect (mc->ctx,
  865. mc->ctx->peer,
  866. "dht",
  867. &dht_set_malicious, mc,
  868. &dht_connect,
  869. &dht_disconnect_malicious,
  870. mc);
  871. }
  872. }
  873. #endif
  874. /**
  875. * Start collecting relevant statistics. If ENABLE_MALICIOUS set, first
  876. * set the malicious peers. If not, then start with PUT operation on active
  877. * peers.
  878. */
  879. static void
  880. start_func()
  881. {
  882. #if ENABLE_MALICIOUS
  883. set_malicious();
  884. return;
  885. #endif
  886. start_profiling();
  887. }
  888. /**
  889. * Remove entry from successor peer hashmap.
  890. * @param cls closure
  891. * @param key current public key
  892. * @param value value in the hash map
  893. * @return #GNUNET_YES if we should continue to iterate,
  894. * #GNUNET_NO if not.
  895. */
  896. static int
  897. hashmap_iterate_remove(void *cls,
  898. const struct GNUNET_HashCode *key,
  899. void *value)
  900. {
  901. GNUNET_assert (GNUNET_YES ==
  902. GNUNET_CONTAINER_multihashmap_remove(successor_peer_hashmap, key, value));
  903. return GNUNET_YES;
  904. }
  905. /**
  906. * Stats callback. Iterate over the hashmap and check if all th peers form
  907. * a virtual ring topology.
  908. *
  909. * @param cls closure
  910. * @param op the operation that has been finished
  911. * @param emsg error message in case the operation has failed; will be NULL if
  912. * operation has executed successfully.
  913. */
  914. static void
  915. successor_stats_cont (void *cls,
  916. struct GNUNET_TESTBED_Operation *op,
  917. const char *emsg)
  918. {
  919. struct GNUNET_HashCode *val;
  920. struct GNUNET_HashCode *start_val;
  921. struct GNUNET_HashCode *key;
  922. int count;
  923. /* Don't schedule the task till we are looking for circle here. */
  924. successor_stats_task = GNUNET_SCHEDULER_NO_TASK;
  925. GNUNET_TESTBED_operation_done (successor_stats_op);
  926. successor_stats_op = NULL;
  927. if (0 == max_searches)
  928. {
  929. start_func();
  930. return;
  931. }
  932. GNUNET_assert (NULL != start_key);
  933. start_val = GNUNET_CONTAINER_multihashmap_get (successor_peer_hashmap,
  934. start_key);
  935. GNUNET_assert (NULL != start_val);
  936. val = start_val;
  937. for (count = 0; count < num_peers; count++)
  938. {
  939. key = val;
  940. val = GNUNET_CONTAINER_multihashmap_get (successor_peer_hashmap,
  941. key);
  942. if (NULL == val)
  943. break;
  944. /* Remove the entry from hashmap. This is done to take care of loop. */
  945. if (GNUNET_NO ==
  946. GNUNET_CONTAINER_multihashmap_remove (successor_peer_hashmap,
  947. key, val))
  948. {
  949. DEBUG ("Failed to remove entry from hashmap\n");
  950. break;
  951. }
  952. /* If a peer has its own identity as its successor. */
  953. if (0 == memcmp(key, val, sizeof (struct GNUNET_HashCode)))
  954. break;
  955. }
  956. GNUNET_assert (GNUNET_SYSERR !=
  957. GNUNET_CONTAINER_multihashmap_iterate (successor_peer_hashmap,
  958. &hashmap_iterate_remove,
  959. NULL));
  960. successor_peer_hashmap = GNUNET_CONTAINER_multihashmap_create (num_peers,
  961. GNUNET_NO);
  962. if ((start_val == val) && (count == num_peers))
  963. {
  964. DEBUG("CIRCLE COMPLETED after %u tries", tries);
  965. if(GNUNET_SCHEDULER_NO_TASK == successor_stats_task)
  966. {
  967. start_func();
  968. }
  969. return;
  970. }
  971. else
  972. {
  973. if (max_searches == ++tries)
  974. {
  975. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  976. "Maximum tries %u exceeded while checking successor TOTAL TRIES %u"
  977. " circle formation. Exiting\n",
  978. max_searches,tries);
  979. if (GNUNET_SCHEDULER_NO_TASK != successor_stats_task)
  980. {
  981. successor_stats_task = GNUNET_SCHEDULER_NO_TASK;
  982. }
  983. if(GNUNET_SCHEDULER_NO_TASK == successor_stats_task)
  984. {
  985. start_func();
  986. }
  987. return;
  988. }
  989. else
  990. {
  991. flag = 0;
  992. successor_stats_task = GNUNET_SCHEDULER_add_delayed (delay_stats,
  993. &collect_stats, cls);
  994. }
  995. }
  996. }
  997. /**
  998. * Process successor statistic values.
  999. *
  1000. * @param cls closure
  1001. * @param peer the peer the statistic belong to
  1002. * @param subsystem name of subsystem that created the statistic
  1003. * @param name the name of the datum
  1004. * @param value the current value
  1005. * @param is_persistent GNUNET_YES if the value is persistent, GNUNET_NO if not
  1006. * @return GNUNET_OK to continue, GNUNET_SYSERR to abort iteration
  1007. */
  1008. static int
  1009. successor_stats_iterator (void *cls,
  1010. const struct GNUNET_TESTBED_Peer *peer,
  1011. const char *subsystem,
  1012. const char *name,
  1013. uint64_t value,
  1014. int is_persistent)
  1015. {
  1016. static const char *key_string = "XDHT";
  1017. if (0 == max_searches)
  1018. return GNUNET_OK;
  1019. if (0 == strncmp (key_string, name, strlen (key_string)))
  1020. {
  1021. char *my_id_str;
  1022. char successor_str[13];
  1023. char truncated_my_id_str[13];
  1024. char truncated_successor_str[13];
  1025. struct GNUNET_HashCode *my_id_key;
  1026. struct GNUNET_HashCode *succ_key;
  1027. strtok((char *)name,":");
  1028. my_id_str = strtok(NULL,":");
  1029. strncpy(truncated_my_id_str, my_id_str, 12);
  1030. truncated_my_id_str[12] = '\0';
  1031. my_id_key = GNUNET_new(struct GNUNET_HashCode);
  1032. GNUNET_CRYPTO_hash (truncated_my_id_str, sizeof(truncated_my_id_str),my_id_key);
  1033. GNUNET_STRINGS_data_to_string(&value, sizeof(uint64_t), successor_str, 13);
  1034. strncpy(truncated_successor_str, successor_str, 12);
  1035. truncated_successor_str[12] ='\0';
  1036. succ_key = GNUNET_new(struct GNUNET_HashCode);
  1037. GNUNET_CRYPTO_hash (truncated_successor_str, sizeof(truncated_successor_str),succ_key);
  1038. if (0 == flag)
  1039. {
  1040. GNUNET_assert(NULL != my_id_key);
  1041. start_key = my_id_key;
  1042. GNUNET_assert(NULL != start_key);
  1043. flag = 1;
  1044. }
  1045. GNUNET_CONTAINER_multihashmap_put (successor_peer_hashmap,
  1046. my_id_key, (void *)succ_key,
  1047. GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);
  1048. }
  1049. return GNUNET_OK;
  1050. }
  1051. /*
  1052. * Task that collects peer and its corresponding successors.
  1053. *
  1054. * @param cls Closure (NULL).
  1055. * @param tc Task Context.
  1056. */
  1057. static void
  1058. collect_stats (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
  1059. {
  1060. if ((GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason) != 0)
  1061. return;
  1062. GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Start collecting statistics...\n");
  1063. GNUNET_assert(NULL != testbed_handles);
  1064. if (0 != max_searches)
  1065. successor_peer_hashmap = GNUNET_CONTAINER_multihashmap_create (num_peers,
  1066. GNUNET_NO);
  1067. successor_stats_op =
  1068. GNUNET_TESTBED_get_statistics (num_peers, testbed_handles,
  1069. "dht", NULL,
  1070. successor_stats_iterator,
  1071. successor_stats_cont, cls);
  1072. GNUNET_assert(NULL != successor_stats_op);
  1073. }
  1074. /**
  1075. * Callback called when DHT service on the peer is started
  1076. *
  1077. * @param cls the context
  1078. * @param op the operation that has been finished
  1079. * @param emsg error message in case the operation has failed; will be NULL if
  1080. * operation has executed successfully.
  1081. */
  1082. static void
  1083. service_started (void *cls,
  1084. struct GNUNET_TESTBED_Operation *op,
  1085. const char *emsg)
  1086. {
  1087. struct Context *ctx = cls;
  1088. GNUNET_assert (NULL != ctx);
  1089. GNUNET_assert (NULL != ctx->op);
  1090. GNUNET_TESTBED_operation_done (ctx->op);
  1091. ctx->op = NULL;
  1092. peers_started++;
  1093. DEBUG("Peers Started = %d; num_peers = %d \n", peers_started, num_peers);
  1094. if (GNUNET_SCHEDULER_NO_TASK == successor_stats_task && peers_started == num_peers)
  1095. {
  1096. DEBUG("successor_stats_task \n");
  1097. struct Collect_Stat_Context *collect_stat_cls = GNUNET_new(struct Collect_Stat_Context);
  1098. collect_stat_cls->service_connect_ctx = cls;
  1099. collect_stat_cls->op = op;
  1100. successor_stats_task = GNUNET_SCHEDULER_add_delayed (delay_stats,
  1101. &collect_stats,
  1102. collect_stat_cls);
  1103. }
  1104. }
  1105. /**
  1106. * Signature of a main function for a testcase.
  1107. *
  1108. * @param cls closure
  1109. * @param h the run handle
  1110. * @param num_peers number of peers in 'peers'
  1111. * @param peers handle to peers run in the testbed
  1112. * @param links_succeeded the number of overlay link connection attempts that
  1113. * succeeded
  1114. * @param links_failed the number of overlay link
  1115. */
  1116. static void
  1117. test_run (void *cls,
  1118. struct GNUNET_TESTBED_RunHandle *h,
  1119. unsigned int num_peers, struct GNUNET_TESTBED_Peer **peers,
  1120. unsigned int links_succeeded,
  1121. unsigned int links_failed)
  1122. {
  1123. unsigned int cnt;
  1124. unsigned int ac_cnt;
  1125. testbed_handles = peers;
  1126. if (NULL == peers)
  1127. {
  1128. /* exit */
  1129. GNUNET_assert (0);
  1130. }
  1131. INFO ("%u peers started\n", num_peers);
  1132. a_ctx = GNUNET_malloc (sizeof (struct Context) * num_peers);
  1133. /* select the peers which actively participate in profiling */
  1134. n_active = num_peers * PUT_PROBABILITY / 100;
  1135. if (0 == n_active)
  1136. {
  1137. GNUNET_SCHEDULER_shutdown ();
  1138. GNUNET_free (a_ctx);
  1139. return;
  1140. }
  1141. a_ac = GNUNET_malloc (n_active * sizeof (struct ActiveContext));
  1142. ac_cnt = 0;
  1143. #if ENABLE_MALICIOUS
  1144. unsigned int malicious_peers;
  1145. if(PUT_PROBABILITY + MALICIOUS_PROBABILITY > 100)
  1146. {
  1147. DEBUG ("Reduce either number of malicious peer or active peers. ");
  1148. GNUNET_SCHEDULER_shutdown ();
  1149. GNUNET_free (a_ctx);
  1150. return;
  1151. }
  1152. /* Select the peers which should act maliciously. */
  1153. n_malicious = num_peers * MALICIOUS_PROBABILITY / 100;
  1154. a_mc = GNUNET_malloc (n_malicious * sizeof (struct MaliciousContext));
  1155. malicious_peers = 0;
  1156. for (cnt = 0; cnt < num_peers && malicious_peers < n_malicious; cnt++)
  1157. {
  1158. if (GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 100) >=
  1159. MALICIOUS_PROBABILITY)
  1160. continue;
  1161. a_ctx[cnt].mc = &a_mc[malicious_peers];
  1162. a_mc[malicious_peers].ctx = &a_ctx[cnt];
  1163. malicious_peers++;
  1164. }
  1165. n_malicious = malicious_peers;
  1166. INFO ("Malicious Peers: %u\n",malicious_peers);
  1167. #endif
  1168. a_ac = GNUNET_malloc (n_active * sizeof (struct ActiveContext));
  1169. ac_cnt = 0;
  1170. for (cnt = 0; cnt < num_peers && ac_cnt < n_active; cnt++)
  1171. {
  1172. if ((GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 100) >=
  1173. PUT_PROBABILITY))
  1174. continue;
  1175. #if ENABLE_MALICIOUS
  1176. if(a_ctx[ac_cnt].mc != NULL)
  1177. continue;
  1178. #endif
  1179. a_ctx[cnt].ac = &a_ac[ac_cnt];
  1180. a_ac[ac_cnt].ctx = &a_ctx[cnt];
  1181. ac_cnt++;
  1182. }
  1183. n_active = ac_cnt;
  1184. INFO ("Active peers: %u\n", n_active);
  1185. /* start DHT service on all peers */
  1186. for (cnt = 0; cnt < num_peers; cnt++)
  1187. {
  1188. a_ctx[cnt].peer = peers[cnt];
  1189. a_ctx[cnt].op = GNUNET_TESTBED_peer_manage_service (&a_ctx[cnt],
  1190. peers[cnt],
  1191. "dht",
  1192. &service_started,
  1193. &a_ctx[cnt],
  1194. 1);
  1195. }
  1196. }
  1197. /**
  1198. * Main function that will be run by the scheduler.
  1199. *
  1200. * @param cls closure
  1201. * @param args remaining command-line arguments
  1202. * @param cfgfile name of the configuration file used (for saving, can be NULL!)
  1203. * @param config configuration
  1204. */
  1205. static void
  1206. run (void *cls, char *const *args, const char *cfgfile,
  1207. const struct GNUNET_CONFIGURATION_Handle *config)
  1208. {
  1209. uint64_t event_mask;
  1210. if (0 == num_peers)
  1211. {
  1212. GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Exiting as the number of peers is %u\n"),
  1213. num_peers);
  1214. return;
  1215. }
  1216. cfg = GNUNET_CONFIGURATION_dup (config);
  1217. event_mask = 0;
  1218. GNUNET_TESTBED_run (hosts_file, cfg, num_peers, event_mask, NULL,
  1219. NULL, &test_run, NULL);
  1220. GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &do_shutdown,
  1221. NULL);
  1222. }
  1223. /**
  1224. * Main function.
  1225. *
  1226. * @return 0 on success
  1227. */
  1228. int
  1229. main (int argc, char *const *argv)
  1230. {
  1231. int rc;
  1232. static struct GNUNET_GETOPT_CommandLineOption options[] = {
  1233. {'n', "peers", "COUNT",
  1234. gettext_noop ("number of peers to start"),
  1235. 1, &GNUNET_GETOPT_set_uint, &num_peers},
  1236. {'s', "searches", "COUNT",
  1237. gettext_noop ("maximum number of times we try to search for successor circle formation (0 for R5N)"),
  1238. 1, &GNUNET_GETOPT_set_uint, &max_searches},
  1239. {'H', "hosts", "FILENAME",
  1240. gettext_noop ("name of the file with the login information for the testbed"),
  1241. 1, &GNUNET_GETOPT_set_string, &hosts_file},
  1242. {'D', "delay", "DELAY",
  1243. gettext_noop ("delay between rounds for collecting statistics (default: 30 sec)"),
  1244. 1, &GNUNET_GETOPT_set_relative_time, &delay_stats},
  1245. {'P', "PUT-delay", "DELAY",
  1246. gettext_noop ("delay to start doing PUTs (default: 1 sec)"),
  1247. 1, &GNUNET_GETOPT_set_relative_time, &delay_put},
  1248. {'G', "GET-delay", "DELAY",
  1249. gettext_noop ("delay to start doing GETs (default: 5 min)"),
  1250. 1, &GNUNET_GETOPT_set_relative_time, &delay_get},
  1251. {'r', "replication", "DEGREE",
  1252. gettext_noop ("replication degree for DHT PUTs"),
  1253. 1, &GNUNET_GETOPT_set_uint, &replication},
  1254. {'t', "timeout", "TIMEOUT",
  1255. gettext_noop ("timeout for DHT PUT and GET requests (default: 1 min)"),
  1256. 1, &GNUNET_GETOPT_set_relative_time, &timeout},
  1257. GNUNET_GETOPT_OPTION_END
  1258. };
  1259. max_searches = 5;
  1260. if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
  1261. return 2;
  1262. /* set default delays */
  1263. delay_stats = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10);
  1264. delay_put = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10);
  1265. delay_get = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10);
  1266. timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10);
  1267. replication = 1; /* default replication */
  1268. rc = 0;
  1269. if (GNUNET_OK !=
  1270. GNUNET_PROGRAM_run (argc, argv, "dht-profiler",
  1271. gettext_noop
  1272. ("Measure quality and performance of the DHT service."),
  1273. options, &run, NULL))
  1274. rc = 1;
  1275. return rc;
  1276. }