testbed_api_topology.c 42 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661
  1. /*
  2. This file is part of GNUnet
  3. Copyright (C) 2008--2013 GNUnet e.V.
  4. GNUnet is free software: you can redistribute it and/or modify it
  5. under the terms of the GNU Affero General Public License as published
  6. by the Free Software Foundation, either version 3 of the License,
  7. or (at your 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. Affero General Public License for more details.
  12. You should have received a copy of the GNU Affero General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. SPDX-License-Identifier: AGPL3.0-or-later
  15. */
  16. /**
  17. * @file testbed/testbed_api_topology.c
  18. * @brief topology-generation functions
  19. * @author Christian Grothoff
  20. */
  21. #include "platform.h"
  22. #include "gnunet_testbed_service.h"
  23. #include "testbed_api.h"
  24. #include "testbed_api_peers.h"
  25. #include "testbed_api_operations.h"
  26. #include "testbed_api_topology.h"
  27. /**
  28. * Generic loggins shorthand
  29. */
  30. #define LOG(kind, ...) \
  31. GNUNET_log_from (kind, "testbed-api-topology", __VA_ARGS__)
  32. /**
  33. * Default number of retires
  34. */
  35. #define DEFAULT_RETRY_CNT 3
  36. /**
  37. * Context information for topology operations
  38. */
  39. struct TopologyContext;
  40. /**
  41. * Representation of an overlay link
  42. */
  43. struct OverlayLink
  44. {
  45. /**
  46. * An operation corresponding to this link
  47. */
  48. struct GNUNET_TESTBED_Operation *op;
  49. /**
  50. * The topology context this link is a part of
  51. */
  52. struct TopologyContext *tc;
  53. /**
  54. * position of peer A's handle in peers array
  55. */
  56. uint32_t A;
  57. /**
  58. * position of peer B's handle in peers array
  59. */
  60. uint32_t B;
  61. };
  62. /**
  63. * Representation of an underlay link
  64. */
  65. struct UnderlayLink
  66. {
  67. /**
  68. * position of peer A's handle in peers array
  69. */
  70. uint32_t A;
  71. /**
  72. * position of peer B's handle in peers array
  73. */
  74. uint32_t B;
  75. /**
  76. * Bandwidth of the link in bytes per second
  77. */
  78. uint32_t bandwidth;
  79. /**
  80. * Latency of the link in milliseconds
  81. */
  82. uint32_t latency;
  83. /**
  84. * Loss in the link in percentage of message dropped
  85. */
  86. uint32_t loss;
  87. };
  88. struct RetryListEntry
  89. {
  90. /**
  91. * the next pointer for the DLL
  92. */
  93. struct RetryListEntry *next;
  94. /**
  95. * the prev pointer for the DLL
  96. */
  97. struct RetryListEntry *prev;
  98. /**
  99. * The link to be retired
  100. */
  101. struct OverlayLink *link;
  102. };
  103. /**
  104. * Context information for overlay topologies
  105. */
  106. struct TopologyContextOverlay
  107. {
  108. /**
  109. * The array of peers
  110. */
  111. struct GNUNET_TESTBED_Peer **peers;
  112. /**
  113. * An array of links; this array is of size link_array_size
  114. */
  115. struct OverlayLink *link_array;
  116. /**
  117. * The operation closure
  118. */
  119. void *op_cls;
  120. /**
  121. * topology generation completion callback
  122. */
  123. GNUNET_TESTBED_TopologyCompletionCallback comp_cb;
  124. /**
  125. * The closure for the above callback
  126. */
  127. void *comp_cb_cls;
  128. /**
  129. * DLL head for retry list
  130. */
  131. struct RetryListEntry *rl_head;
  132. /**
  133. * DLL tail for retry list
  134. */
  135. struct RetryListEntry *rl_tail;
  136. /**
  137. * How many retries to do before we give up
  138. */
  139. unsigned int retry_cnt;
  140. /**
  141. * Number of links to try
  142. */
  143. unsigned int nlinks;
  144. /**
  145. * How many links have been completed
  146. */
  147. unsigned int ncompleted;
  148. /**
  149. * Total successfully established overlay connections
  150. */
  151. unsigned int nsuccess;
  152. /**
  153. * Total failed overlay connections
  154. */
  155. unsigned int nfailures;
  156. };
  157. /**
  158. * Topology context information for underlay topologies
  159. */
  160. struct TopologyContextUnderlay
  161. {
  162. /**
  163. * The link array
  164. */
  165. struct UnderlayLink *link_array;
  166. };
  167. /**
  168. * Context information for topology operations
  169. */
  170. struct TopologyContext
  171. {
  172. /**
  173. * The type of this context
  174. */
  175. enum
  176. {
  177. /**
  178. * Type for underlay topology
  179. */
  180. TOPOLOGYCONTEXT_TYPE_UNDERLAY = 0,
  181. /**
  182. * Type for overlay topology
  183. */
  184. TOPOLOGYCONTEXT_TYPE_OVERLAY
  185. } type;
  186. union
  187. {
  188. /**
  189. * Topology context information for overlay topology
  190. */
  191. struct TopologyContextOverlay overlay;
  192. /**
  193. * Topology context information for underlay topology
  194. */
  195. struct TopologyContextUnderlay underlay;
  196. } u;
  197. /**
  198. * The number of peers
  199. */
  200. unsigned int num_peers;
  201. /**
  202. * The size of the link array
  203. */
  204. unsigned int link_array_size;
  205. };
  206. /**
  207. * A array of names representing topologies. Should be in sync with enum
  208. * GNUNET_TESTBED_TopologyOption
  209. */
  210. static const char *topology_strings[] = {
  211. /**
  212. * A clique (everyone connected to everyone else). No options. If there are N
  213. * peers this topology results in (N * (N -1)) connections.
  214. */
  215. "CLIQUE",
  216. /*
  217. * Small-world network (2d torus plus random links). Followed
  218. * by the number of random links to add (unsigned int).
  219. */
  220. "SMALL_WORLD",
  221. /**
  222. * Small-world network (ring plus random links). Followed
  223. * by the number of random links to add (unsigned int).
  224. */
  225. "SMALL_WORLD_RING",
  226. /**
  227. * Ring topology. No options.
  228. */
  229. "RING",
  230. /**
  231. * Star topology. No options.
  232. */
  233. "STAR",
  234. /**
  235. * 2-d torus. No options.
  236. */
  237. "2D_TORUS",
  238. /**
  239. * Random graph. Followed by the number of random links to be established
  240. * (unsigned int)
  241. */
  242. "RANDOM", // GNUNET_TESTBED_TOPOLOGY_ERDOS_RENYI
  243. /**
  244. * Certain percentage of peers are unable to communicate directly
  245. * replicating NAT conditions. Followed by the fraction of
  246. * NAT'ed peers (float).
  247. */
  248. "INTERNAT",
  249. /**
  250. * Scale free topology. Followed by the maximum number of links a node can
  251. * have (unsigned int); and the number of links a new node should have when
  252. * it is added to the network (unsigned int)
  253. */
  254. "SCALE_FREE",
  255. /**
  256. * Straight line topology. No options.
  257. */
  258. "LINE",
  259. /**
  260. * Read a topology from a given file. Followed by the name of the file (const char *).
  261. */
  262. "FROM_FILE",
  263. /**
  264. * All peers are disconnected. No options.
  265. */
  266. "NONE",
  267. /**
  268. * End of strings
  269. */
  270. NULL
  271. };
  272. /**
  273. * Callback to be called when an overlay_link operation complete
  274. *
  275. * @param cls element of the link_op array which points to the corresponding operation
  276. * @param op the operation that has been finished
  277. * @param emsg error message in case the operation has failed; will be NULL if
  278. * operation has executed successfully.
  279. */
  280. static void
  281. overlay_link_completed (void *cls,
  282. struct GNUNET_TESTBED_Operation *op,
  283. const char *emsg)
  284. {
  285. struct OverlayLink *link = cls;
  286. struct TopologyContext *tc;
  287. struct TopologyContextOverlay *overlay;
  288. struct RetryListEntry *retry_entry;
  289. GNUNET_assert (op == link->op);
  290. GNUNET_TESTBED_operation_done (op);
  291. link->op = NULL;
  292. tc = link->tc;
  293. GNUNET_assert (TOPOLOGYCONTEXT_TYPE_OVERLAY == tc->type);
  294. overlay = &tc->u.overlay;
  295. if (NULL != emsg)
  296. {
  297. overlay->nfailures++;
  298. if (0 != overlay->retry_cnt)
  299. {
  300. LOG (GNUNET_ERROR_TYPE_WARNING,
  301. "Error while establishing a link: %s -- Retrying\n",
  302. emsg);
  303. retry_entry = GNUNET_new (struct RetryListEntry);
  304. retry_entry->link = link;
  305. GNUNET_CONTAINER_DLL_insert_tail (overlay->rl_head,
  306. overlay->rl_tail,
  307. retry_entry);
  308. }
  309. }
  310. else
  311. overlay->nsuccess++;
  312. overlay->ncompleted++;
  313. if (overlay->ncompleted < overlay->nlinks)
  314. return;
  315. if ((0 != overlay->retry_cnt) && (NULL != overlay->rl_head))
  316. {
  317. overlay->retry_cnt--;
  318. overlay->ncompleted = 0;
  319. overlay->nlinks = 0;
  320. while (NULL != (retry_entry = overlay->rl_head))
  321. {
  322. link = retry_entry->link;
  323. link->op =
  324. GNUNET_TESTBED_overlay_connect (overlay->op_cls,
  325. &overlay_link_completed,
  326. link,
  327. overlay->peers[link->A],
  328. overlay->peers[link->B]);
  329. overlay->nlinks++;
  330. GNUNET_CONTAINER_DLL_remove (overlay->rl_head,
  331. overlay->rl_tail,
  332. retry_entry);
  333. GNUNET_free (retry_entry);
  334. }
  335. return;
  336. }
  337. if (NULL != overlay->comp_cb)
  338. {
  339. overlay->comp_cb (overlay->comp_cb_cls,
  340. overlay->nsuccess,
  341. overlay->nfailures);
  342. }
  343. }
  344. /**
  345. * Function called when a overlay connect operation is ready
  346. *
  347. * @param cls the Topology context
  348. */
  349. static void
  350. opstart_overlay_configure_topology (void *cls)
  351. {
  352. struct TopologyContext *tc = cls;
  353. struct TopologyContextOverlay *overlay;
  354. unsigned int p;
  355. GNUNET_assert (TOPOLOGYCONTEXT_TYPE_OVERLAY == tc->type);
  356. overlay = &tc->u.overlay;
  357. overlay->nlinks = tc->link_array_size;
  358. for (p = 0; p < tc->link_array_size; p++)
  359. {
  360. overlay->link_array[p].op =
  361. GNUNET_TESTBED_overlay_connect (overlay->op_cls,
  362. &overlay_link_completed,
  363. &overlay->link_array[p],
  364. overlay->peers[overlay->link_array[p].A],
  365. overlay->peers[overlay->link_array[p].B]);
  366. }
  367. }
  368. /**
  369. * Callback which will be called when overlay connect operation is released
  370. *
  371. * @param cls the Topology context
  372. */
  373. static void
  374. oprelease_overlay_configure_topology (void *cls)
  375. {
  376. struct TopologyContext *tc = cls;
  377. struct TopologyContextOverlay *overlay;
  378. struct RetryListEntry *retry_entry;
  379. unsigned int p;
  380. GNUNET_assert (TOPOLOGYCONTEXT_TYPE_OVERLAY == tc->type);
  381. overlay = &tc->u.overlay;
  382. while (NULL != (retry_entry = overlay->rl_head))
  383. {
  384. GNUNET_CONTAINER_DLL_remove (overlay->rl_head, overlay->rl_tail,
  385. retry_entry);
  386. GNUNET_free (retry_entry);
  387. }
  388. if (NULL != overlay->link_array)
  389. {
  390. for (p = 0; p < tc->link_array_size; p++)
  391. if (NULL != overlay->link_array[p].op)
  392. GNUNET_TESTBED_operation_done (overlay->link_array[p].op);
  393. GNUNET_free (overlay->link_array);
  394. }
  395. GNUNET_free (tc);
  396. }
  397. /**
  398. * Populates the OverlayLink structure.
  399. *
  400. * @param offset the offset of the link array to use
  401. * @param A the peer A. Should be different from B
  402. * @param B the peer B. Should be different from A
  403. * @param tc the TopologyContext
  404. * @return
  405. */
  406. static void
  407. make_link (unsigned int offset,
  408. uint32_t A,
  409. uint32_t B,
  410. struct TopologyContext *tc)
  411. {
  412. GNUNET_assert (A != B);
  413. switch (tc->type)
  414. {
  415. case TOPOLOGYCONTEXT_TYPE_OVERLAY:
  416. {
  417. struct TopologyContextOverlay *overlay;
  418. struct OverlayLink *olink;
  419. overlay = &tc->u.overlay;
  420. GNUNET_assert (offset < tc->link_array_size);
  421. olink = &overlay->link_array[offset];
  422. LOG (GNUNET_ERROR_TYPE_DEBUG, "Connecting peer %u to %u\n", B, A);
  423. olink->A = A;
  424. olink->B = B;
  425. olink->op = NULL;
  426. olink->tc = tc;
  427. }
  428. break;
  429. case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
  430. {
  431. struct TopologyContextUnderlay *underlay;
  432. struct UnderlayLink *ulink;
  433. underlay = &tc->u.underlay;
  434. GNUNET_assert (offset < tc->link_array_size);
  435. ulink = &underlay->link_array[offset];
  436. ulink->A = A;
  437. ulink->B = B;
  438. }
  439. break;
  440. }
  441. }
  442. /**
  443. * Generates line topology
  444. *
  445. * @param tc the topology context
  446. */
  447. static void
  448. gen_topo_line (struct TopologyContext *tc)
  449. {
  450. unsigned int cnt;
  451. tc->link_array_size = tc->num_peers - 1;
  452. switch (tc->type)
  453. {
  454. case TOPOLOGYCONTEXT_TYPE_OVERLAY:
  455. {
  456. struct TopologyContextOverlay *overlay;
  457. overlay = &tc->u.overlay;
  458. overlay->link_array =
  459. GNUNET_new_array (tc->link_array_size,
  460. struct OverlayLink);
  461. }
  462. break;
  463. case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
  464. {
  465. struct TopologyContextUnderlay *underlay;
  466. underlay = &tc->u.underlay;
  467. underlay->link_array =
  468. GNUNET_new_array (tc->link_array_size,
  469. struct UnderlayLink);
  470. }
  471. break;
  472. }
  473. for (cnt = 0; cnt < (tc->link_array_size); cnt++)
  474. make_link (cnt, cnt, cnt + 1, tc);
  475. }
  476. /**
  477. * Generates star topology
  478. *
  479. * @param tc the topology context
  480. */
  481. static void
  482. gen_topo_star (struct TopologyContext *tc)
  483. {
  484. unsigned int cnt;
  485. tc->link_array_size = tc->num_peers - 1;
  486. switch (tc->type)
  487. {
  488. case TOPOLOGYCONTEXT_TYPE_OVERLAY:
  489. {
  490. struct TopologyContextOverlay *overlay;
  491. overlay = &tc->u.overlay;
  492. overlay->link_array =
  493. GNUNET_new_array (tc->link_array_size,
  494. struct OverlayLink);
  495. }
  496. break;
  497. case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
  498. {
  499. struct TopologyContextUnderlay *underlay;
  500. underlay = &tc->u.underlay;
  501. underlay->link_array =
  502. GNUNET_new_array (tc->link_array_size,
  503. struct UnderlayLink);
  504. }
  505. break;
  506. }
  507. for (cnt = tc->link_array_size; cnt; cnt--)
  508. make_link (cnt - 1,
  509. 0,
  510. cnt,
  511. tc);
  512. }
  513. /**
  514. * Generates ring topology
  515. *
  516. * @param tc the topology context
  517. */
  518. static void
  519. gen_topo_ring (struct TopologyContext *tc)
  520. {
  521. gen_topo_line (tc);
  522. tc->link_array_size++;
  523. switch (tc->type)
  524. {
  525. case TOPOLOGYCONTEXT_TYPE_OVERLAY:
  526. {
  527. struct TopologyContextOverlay *overlay;
  528. overlay = &tc->u.overlay;
  529. overlay->link_array =
  530. GNUNET_realloc (overlay->link_array, sizeof(struct OverlayLink)
  531. * tc->link_array_size);
  532. }
  533. break;
  534. case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
  535. {
  536. struct TopologyContextUnderlay *underlay;
  537. underlay = &tc->u.underlay;
  538. underlay->link_array =
  539. GNUNET_realloc (underlay->link_array, sizeof(struct UnderlayLink)
  540. * tc->link_array_size);
  541. }
  542. break;
  543. }
  544. make_link (tc->link_array_size - 1, tc->num_peers - 1, 0, tc);
  545. }
  546. /**
  547. * Returns the number of links that are required to generate a 2d torus for the
  548. * given number of peers. Also returns the arrangment (number of rows and the
  549. * length of each row)
  550. *
  551. * @param num_peers number of peers
  552. * @param rows number of rows in the 2d torus. Can be NULL
  553. * @param rows_len the length of each row. This array will be allocated
  554. * fresh. The caller should free it. Can be NULL
  555. * @return the number of links that are required to generate a 2d torus for the
  556. * given number of peers
  557. */
  558. unsigned int
  559. GNUNET_TESTBED_2dtorus_calc_links (unsigned int num_peers, unsigned int *rows,
  560. unsigned int **rows_len)
  561. {
  562. double sq;
  563. unsigned int sq_floor;
  564. unsigned int _rows;
  565. unsigned int *_rows_len;
  566. unsigned int x;
  567. unsigned int y;
  568. unsigned int _num_peers;
  569. unsigned int cnt;
  570. sq = sqrt (num_peers);
  571. sq = floor (sq);
  572. sq_floor = (unsigned int) sq;
  573. _rows = (sq_floor + 1);
  574. _rows_len = GNUNET_malloc (sizeof(unsigned int) * _rows);
  575. for (y = 0; y < _rows - 1; y++)
  576. _rows_len[y] = sq_floor;
  577. _num_peers = sq_floor * sq_floor;
  578. cnt = (_num_peers < 2) ? _num_peers : 2 * _num_peers;
  579. x = 0;
  580. y = 0;
  581. while (_num_peers < num_peers)
  582. {
  583. if (x < y)
  584. _rows_len[_rows - 1] = ++x;
  585. else
  586. _rows_len[y++]++;
  587. _num_peers++;
  588. }
  589. cnt += (x < 2) ? x : 2 * x;
  590. cnt += (y < 2) ? y : 2 * y;
  591. if (0 == _rows_len[_rows - 1])
  592. _rows--;
  593. if (NULL != rows)
  594. *rows = _rows;
  595. if (NULL != rows_len)
  596. *rows_len = _rows_len;
  597. else
  598. GNUNET_free (_rows_len);
  599. return cnt;
  600. }
  601. /**
  602. * Generates ring topology
  603. *
  604. * @param tc the topology context
  605. */
  606. static void
  607. gen_topo_2dtorus (struct TopologyContext *tc)
  608. {
  609. unsigned int rows;
  610. unsigned int *rows_len;
  611. unsigned int x;
  612. unsigned int y;
  613. unsigned int cnt;
  614. unsigned int offset;
  615. tc->link_array_size =
  616. GNUNET_TESTBED_2dtorus_calc_links (tc->num_peers, &rows, &rows_len);
  617. switch (tc->type)
  618. {
  619. case TOPOLOGYCONTEXT_TYPE_OVERLAY:
  620. {
  621. struct TopologyContextOverlay *overlay;
  622. overlay = &tc->u.overlay;
  623. overlay->link_array =
  624. GNUNET_malloc (sizeof(struct OverlayLink) * tc->link_array_size);
  625. }
  626. break;
  627. case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
  628. {
  629. struct TopologyContextUnderlay *underlay;
  630. underlay = &tc->u.underlay;
  631. underlay->link_array =
  632. GNUNET_malloc (sizeof(struct UnderlayLink) * tc->link_array_size);
  633. break;
  634. }
  635. }
  636. cnt = 0;
  637. offset = 0;
  638. for (y = 0; y < rows; y++)
  639. {
  640. for (x = 0; x < rows_len[y] - 1; x++)
  641. {
  642. make_link (cnt, offset + x, offset + x + 1, tc);
  643. cnt++;
  644. }
  645. if (0 == x)
  646. break;
  647. make_link (cnt, offset + x, offset, tc);
  648. cnt++;
  649. offset += rows_len[y];
  650. }
  651. for (x = 0; x < rows_len[0]; x++)
  652. {
  653. offset = 0;
  654. for (y = 0; y < rows - 1; y++)
  655. {
  656. if (x >= rows_len[y + 1])
  657. break;
  658. GNUNET_assert (x < rows_len[y + 1]);
  659. make_link (cnt, offset + x, offset + rows_len[y] + x, tc);
  660. offset += rows_len[y];
  661. cnt++;
  662. }
  663. if (0 == offset)
  664. break;
  665. make_link (cnt, offset + x, x, tc);
  666. cnt++;
  667. }
  668. GNUNET_assert (cnt == tc->link_array_size);
  669. GNUNET_free (rows_len);
  670. }
  671. /**
  672. * Generates ring topology
  673. *
  674. * @param tc the topology context
  675. * @param links the number of random links to establish
  676. * @param append #GNUNET_YES to add links to existing link array; #GNUNET_NO to
  677. * create a new link array
  678. */
  679. static void
  680. gen_topo_random (struct TopologyContext *tc,
  681. unsigned int links,
  682. int append)
  683. {
  684. unsigned int cnt;
  685. unsigned int index;
  686. uint32_t A_rand;
  687. uint32_t B_rand;
  688. if (1 == tc->num_peers)
  689. return;
  690. if (GNUNET_YES == append)
  691. {
  692. index = tc->link_array_size;
  693. tc->link_array_size += links;
  694. }
  695. else
  696. {
  697. index = 0;
  698. tc->link_array_size = links;
  699. }
  700. switch (tc->type)
  701. {
  702. case TOPOLOGYCONTEXT_TYPE_OVERLAY:
  703. {
  704. struct TopologyContextOverlay *overlay;
  705. overlay = &tc->u.overlay;
  706. if (GNUNET_YES != append)
  707. {
  708. GNUNET_assert (NULL == overlay->link_array);
  709. overlay->link_array =
  710. GNUNET_malloc (sizeof(struct OverlayLink) * tc->link_array_size);
  711. break;
  712. }
  713. GNUNET_assert ((0 < tc->link_array_size) && (NULL !=
  714. overlay->link_array));
  715. overlay->link_array =
  716. GNUNET_realloc (overlay->link_array,
  717. sizeof(struct OverlayLink) * tc->link_array_size);
  718. break;
  719. }
  720. case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
  721. {
  722. struct TopologyContextUnderlay *underlay;
  723. underlay = &tc->u.underlay;
  724. if (GNUNET_YES != append)
  725. {
  726. GNUNET_assert (NULL == underlay->link_array);
  727. underlay->link_array =
  728. GNUNET_malloc (sizeof(struct UnderlayLink) * tc->link_array_size);
  729. break;
  730. }
  731. GNUNET_assert ((0 < tc->link_array_size) && (NULL !=
  732. underlay->link_array));
  733. underlay->link_array =
  734. GNUNET_realloc (underlay->link_array,
  735. sizeof(struct UnderlayLink) * tc->link_array_size);
  736. break;
  737. }
  738. }
  739. for (cnt = 0; cnt < links; cnt++)
  740. {
  741. do
  742. {
  743. A_rand =
  744. GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, tc->num_peers);
  745. B_rand =
  746. GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, tc->num_peers);
  747. }
  748. while (A_rand == B_rand);
  749. make_link (index + cnt, A_rand, B_rand, tc);
  750. }
  751. }
  752. /**
  753. * Generates scale free network. Its construction is described in:
  754. *
  755. * "Emergence of Scaling in Random Networks." Science 286, 509-512, 1999.
  756. *
  757. * @param tc the topology context
  758. * @param cap maximum allowed node degree
  759. * @param m number of edges to establish for a new node when it is added to the
  760. * network
  761. */
  762. static void
  763. gen_topo_scale_free (struct TopologyContext *tc,
  764. uint16_t cap,
  765. uint8_t m)
  766. {
  767. unsigned int *deg;
  768. unsigned int *etab;
  769. unsigned int *used;
  770. unsigned int etaboff;
  771. unsigned int cnt;
  772. unsigned int cnt2;
  773. unsigned int peer;
  774. unsigned int random_peer;
  775. unsigned int links;
  776. unsigned int off;
  777. unsigned int redo_threshold;
  778. etaboff = 0;
  779. tc->link_array_size = tc->num_peers * m;
  780. switch (tc->type)
  781. {
  782. case TOPOLOGYCONTEXT_TYPE_OVERLAY:
  783. {
  784. struct TopologyContextOverlay *overlay;
  785. overlay = &tc->u.overlay;
  786. overlay->link_array = GNUNET_malloc_large (sizeof(struct OverlayLink)
  787. * tc->link_array_size);
  788. }
  789. break;
  790. case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
  791. {
  792. struct TopologyContextUnderlay *underlay;
  793. underlay = &tc->u.underlay;
  794. underlay->link_array = GNUNET_malloc_large (sizeof(struct UnderlayLink)
  795. * tc->link_array_size);
  796. }
  797. break;
  798. }
  799. etab = GNUNET_malloc_large (sizeof(unsigned int) * 2 * tc->link_array_size);
  800. deg = GNUNET_malloc (sizeof(unsigned int) * tc->num_peers);
  801. used = GNUNET_malloc (sizeof(unsigned int) * m);
  802. /* start by connecting peer 1 to peer 0 */
  803. make_link (0, 0, 1, tc);
  804. deg[0]++;
  805. deg[1]++;
  806. etab[etaboff++] = 0;
  807. etab[etaboff++] = 1;
  808. links = 1;
  809. for (peer = 2; peer < tc->num_peers; peer++)
  810. {
  811. if (cap < deg[peer])
  812. continue;
  813. for (cnt = 0; cnt < GNUNET_MIN (peer, m); cnt++)
  814. {
  815. redo_threshold = 0;
  816. redo:
  817. off = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, etaboff);
  818. random_peer = etab[off];
  819. if (cap < deg[random_peer])
  820. {
  821. if (++redo_threshold > GNUNET_MAX (1, cap / 2))
  822. {
  823. redo_threshold = 0;
  824. off = 0;
  825. for (cnt2 = 0; cnt2 < etaboff; cnt2++)
  826. {
  827. if (random_peer == etab[cnt2])
  828. {
  829. off++;
  830. continue;
  831. }
  832. etab[cnt2 - off] = etab[cnt2];
  833. }
  834. etaboff -= off;
  835. }
  836. goto redo;
  837. }
  838. for (cnt2 = 0; cnt2 < cnt; cnt2++)
  839. if (random_peer == used[cnt2])
  840. goto redo;
  841. make_link (links + cnt, random_peer, peer, tc);
  842. deg[random_peer]++;
  843. deg[peer]++;
  844. used[cnt] = random_peer;
  845. }
  846. for (cnt = 0; cnt < GNUNET_MIN (peer, m); cnt++)
  847. {
  848. etab[etaboff++] = used[cnt];
  849. etab[etaboff++] = peer;
  850. }
  851. links += GNUNET_MIN (peer, m);
  852. }
  853. GNUNET_free (etab);
  854. GNUNET_free (used);
  855. GNUNET_free (deg);
  856. GNUNET_assert (links <= tc->link_array_size);
  857. tc->link_array_size = links;
  858. switch (tc->type)
  859. {
  860. case TOPOLOGYCONTEXT_TYPE_OVERLAY:
  861. {
  862. struct TopologyContextOverlay *overlay;
  863. overlay = &tc->u.overlay;
  864. overlay->link_array =
  865. GNUNET_realloc (overlay->link_array, sizeof(struct OverlayLink)
  866. * tc->link_array_size);
  867. }
  868. break;
  869. case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
  870. {
  871. struct TopologyContextUnderlay *underlay;
  872. underlay = &tc->u.underlay;
  873. underlay->link_array =
  874. GNUNET_realloc (underlay->link_array, sizeof(struct UnderlayLink)
  875. * tc->link_array_size);
  876. }
  877. break;
  878. }
  879. }
  880. /**
  881. * Generates topology from the given file
  882. *
  883. * @param tc the topology context
  884. * @param filename the filename of the file containing topology data
  885. */
  886. static void
  887. gen_topo_from_file (struct TopologyContext *tc,
  888. const char *filename)
  889. {
  890. char *data;
  891. char *end;
  892. char *buf;
  893. uint64_t fs;
  894. uint64_t offset;
  895. unsigned long int peer_id;
  896. unsigned long int other_peer_id;
  897. enum ParseState
  898. {
  899. /**
  900. * We read the peer index
  901. */
  902. PEER_INDEX,
  903. /**
  904. * We read the other peer indices
  905. */
  906. OTHER_PEER_INDEX,
  907. } state;
  908. int status;
  909. status = GNUNET_SYSERR;
  910. if (GNUNET_YES != GNUNET_DISK_file_test (filename))
  911. {
  912. LOG (GNUNET_ERROR_TYPE_ERROR,
  913. _ ("Topology file %s not found\n"),
  914. filename);
  915. return;
  916. }
  917. if (GNUNET_OK !=
  918. GNUNET_DISK_file_size (filename, &fs, GNUNET_YES, GNUNET_YES))
  919. {
  920. LOG (GNUNET_ERROR_TYPE_ERROR,
  921. _ ("Topology file %s has no data\n"),
  922. filename);
  923. return;
  924. }
  925. data = GNUNET_malloc (fs);
  926. if (fs != GNUNET_DISK_fn_read (filename, data, fs))
  927. {
  928. LOG (GNUNET_ERROR_TYPE_ERROR,
  929. _ ("Topology file %s cannot be read\n"),
  930. filename);
  931. goto _exit;
  932. }
  933. offset = 0;
  934. peer_id = 0;
  935. state = PEER_INDEX;
  936. while (offset < fs)
  937. {
  938. if (0 != isspace ((unsigned char) data[offset]))
  939. {
  940. offset++;
  941. continue;
  942. }
  943. switch (state)
  944. {
  945. case PEER_INDEX:
  946. buf = strchr (&data[offset], ':');
  947. if (NULL == buf)
  948. {
  949. LOG (GNUNET_ERROR_TYPE_ERROR,
  950. _ ("Failed to read peer index from toology file: %s"), filename);
  951. goto _exit;
  952. }
  953. *buf = '\0';
  954. errno = 0;
  955. peer_id = (unsigned int) strtoul (&data[offset], &end, 10);
  956. if (0 != errno)
  957. {
  958. LOG (GNUNET_ERROR_TYPE_ERROR,
  959. _ ("Value in given topology file: %s out of range\n"), filename);
  960. goto _exit;
  961. }
  962. if (&data[offset] == end)
  963. {
  964. LOG (GNUNET_ERROR_TYPE_ERROR,
  965. _ ("Failed to read peer index from topology file: %s"), filename);
  966. goto _exit;
  967. }
  968. if (tc->num_peers <= peer_id)
  969. {
  970. LOG (GNUNET_ERROR_TYPE_ERROR,
  971. _ ("Topology file needs more peers than given ones\n"), filename);
  972. goto _exit;
  973. }
  974. state = OTHER_PEER_INDEX;
  975. offset += ((unsigned int) (buf - &data[offset])) + 1;
  976. break;
  977. case OTHER_PEER_INDEX:
  978. errno = 0;
  979. other_peer_id = (unsigned int) strtoul (&data[offset], &end, 10);
  980. if (0 != errno)
  981. {
  982. LOG (GNUNET_ERROR_TYPE_ERROR,
  983. _ ("Value in given topology file: %s out of range\n"), filename);
  984. goto _exit;
  985. }
  986. if (&data[offset] == end)
  987. {
  988. LOG (GNUNET_ERROR_TYPE_ERROR,
  989. _ ("Failed to read peer index from topology file: %s"), filename);
  990. goto _exit;
  991. }
  992. if (tc->num_peers <= other_peer_id)
  993. {
  994. LOG (GNUNET_ERROR_TYPE_ERROR,
  995. _ ("Topology file needs more peers than given ones\n"), filename);
  996. goto _exit;
  997. }
  998. if (peer_id != other_peer_id)
  999. {
  1000. tc->link_array_size++;
  1001. switch (tc->type)
  1002. {
  1003. case TOPOLOGYCONTEXT_TYPE_OVERLAY:
  1004. {
  1005. struct TopologyContextOverlay *overlay;
  1006. overlay = &tc->u.overlay;
  1007. overlay->link_array =
  1008. GNUNET_realloc (overlay->link_array,
  1009. sizeof(struct OverlayLink) * tc->link_array_size);
  1010. }
  1011. break;
  1012. case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
  1013. {
  1014. struct TopologyContextUnderlay *underlay;
  1015. underlay = &tc->u.underlay;
  1016. underlay->link_array =
  1017. GNUNET_realloc (underlay->link_array,
  1018. sizeof(struct UnderlayLink)
  1019. * tc->link_array_size);
  1020. }
  1021. break;
  1022. }
  1023. offset += end - &data[offset];
  1024. make_link (tc->link_array_size - 1, peer_id, other_peer_id, tc);
  1025. }
  1026. else
  1027. LOG (GNUNET_ERROR_TYPE_WARNING,
  1028. _ ("Ignoring to connect peer %u to peer %u\n"),
  1029. peer_id,
  1030. other_peer_id);
  1031. while (('\n' != data[offset]) && ('|' != data[offset]) && (offset < fs))
  1032. offset++;
  1033. if ((offset < fs) &&
  1034. ('\n' == data[offset]))
  1035. state = PEER_INDEX;
  1036. else if ((offset < fs) &&
  1037. ('|' == data[offset]))
  1038. {
  1039. state = OTHER_PEER_INDEX;
  1040. offset++;
  1041. }
  1042. break;
  1043. }
  1044. }
  1045. status = GNUNET_OK;
  1046. _exit:
  1047. GNUNET_free (data);
  1048. if (GNUNET_OK != status)
  1049. {
  1050. LOG (GNUNET_ERROR_TYPE_WARNING,
  1051. "Removing link data read from the file\n");
  1052. tc->link_array_size = 0;
  1053. switch (tc->type)
  1054. {
  1055. case TOPOLOGYCONTEXT_TYPE_OVERLAY:
  1056. {
  1057. struct TopologyContextOverlay *overlay;
  1058. overlay = &tc->u.overlay;
  1059. GNUNET_free_non_null (overlay->link_array);
  1060. overlay->link_array = NULL;
  1061. }
  1062. break;
  1063. case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
  1064. {
  1065. struct TopologyContextUnderlay *underlay;
  1066. underlay = &tc->u.underlay;
  1067. GNUNET_free_non_null (underlay->link_array);
  1068. underlay->link_array = NULL;
  1069. }
  1070. break;
  1071. }
  1072. }
  1073. }
  1074. /**
  1075. * Generates clique topology
  1076. *
  1077. * @param tc the topology context
  1078. */
  1079. static void
  1080. gen_topo_clique (struct TopologyContext *tc)
  1081. {
  1082. unsigned int cnt;
  1083. unsigned int offset;
  1084. unsigned int neighbour;
  1085. tc->link_array_size = tc->num_peers * (tc->num_peers - 1);
  1086. switch (tc->type)
  1087. {
  1088. case TOPOLOGYCONTEXT_TYPE_OVERLAY:
  1089. {
  1090. struct TopologyContextOverlay *overlay;
  1091. overlay = &tc->u.overlay;
  1092. overlay->link_array = GNUNET_new_array (tc->link_array_size,
  1093. struct OverlayLink);
  1094. }
  1095. break;
  1096. case TOPOLOGYCONTEXT_TYPE_UNDERLAY:
  1097. {
  1098. struct TopologyContextUnderlay *underlay;
  1099. underlay = &tc->u.underlay;
  1100. underlay->link_array = GNUNET_new_array (tc->link_array_size,
  1101. struct UnderlayLink);
  1102. }
  1103. }
  1104. offset = 0;
  1105. for (cnt = 0; cnt < tc->num_peers; cnt++)
  1106. {
  1107. for (neighbour = 0; neighbour < tc->num_peers; neighbour++)
  1108. {
  1109. if (neighbour == cnt)
  1110. continue;
  1111. make_link (offset, cnt, neighbour, tc);
  1112. offset++;
  1113. }
  1114. }
  1115. }
  1116. /**
  1117. * Configure overall network topology to have a particular shape.
  1118. *
  1119. * @param op_cls closure argument to give with the operation event
  1120. * @param num_peers number of peers in @a peers
  1121. * @param peers array of @a num_peers with the peers to configure
  1122. * @param topo desired underlay topology to use
  1123. * @param ap topology-specific options
  1124. * @return handle to the operation, NULL if configuring the topology
  1125. * is not allowed at this time
  1126. */
  1127. struct GNUNET_TESTBED_Operation *
  1128. GNUNET_TESTBED_underlay_configure_topology_va (void *op_cls,
  1129. unsigned int num_peers,
  1130. struct GNUNET_TESTBED_Peer
  1131. **peers,
  1132. enum
  1133. GNUNET_TESTBED_TopologyOption
  1134. topo, va_list ap)
  1135. {
  1136. GNUNET_break (0);
  1137. return NULL;
  1138. }
  1139. /**
  1140. * Configure overall network topology to have a particular shape.
  1141. *
  1142. * @param op_cls closure argument to give with the operation event
  1143. * @param num_peers number of peers in @a peers
  1144. * @param peers array of @a num_peers with the peers to configure
  1145. * @param topo desired underlay topology to use
  1146. * @param ... topology-specific options
  1147. * @return handle to the operation, NULL if configuring the topology
  1148. * is not allowed at this time
  1149. */
  1150. struct GNUNET_TESTBED_Operation *
  1151. GNUNET_TESTBED_underlay_configure_topology (void *op_cls,
  1152. unsigned int num_peers,
  1153. struct GNUNET_TESTBED_Peer **peers,
  1154. enum GNUNET_TESTBED_TopologyOption
  1155. topo, ...)
  1156. {
  1157. GNUNET_break (0);
  1158. return NULL;
  1159. }
  1160. /**
  1161. * All peers must have been started before calling this function.
  1162. * This function then connects the given peers in the P2P overlay
  1163. * using the given topology.
  1164. *
  1165. * @param op_cls closure argument to give with the peer connect operation events
  1166. * generated through this function
  1167. * @param num_peers number of peers in @a peers
  1168. * @param peers array of @a num_peers with the peers to configure
  1169. * @param max_connections the maximums number of overlay connections that will
  1170. * be made to achieve the given topology
  1171. * @param comp_cb the completion callback to call when the topology generation
  1172. * is completed
  1173. * @param comp_cb_cls closure for the above completion callback
  1174. * @param topo desired underlay topology to use
  1175. * @param va topology-specific options
  1176. * @return handle to the operation, NULL if connecting these
  1177. * peers is fundamentally not possible at this time (peers
  1178. * not running or underlay disallows) or if num_peers is less than 2
  1179. */
  1180. struct GNUNET_TESTBED_Operation *
  1181. GNUNET_TESTBED_overlay_configure_topology_va (void *op_cls,
  1182. unsigned int num_peers,
  1183. struct GNUNET_TESTBED_Peer **peers,
  1184. unsigned int *max_connections,
  1185. GNUNET_TESTBED_TopologyCompletionCallback
  1186. comp_cb,
  1187. void *comp_cb_cls,
  1188. enum GNUNET_TESTBED_TopologyOption
  1189. topo,
  1190. va_list va)
  1191. {
  1192. struct TopologyContext *tc;
  1193. struct TopologyContextOverlay *overlay;
  1194. struct GNUNET_TESTBED_Operation *op;
  1195. struct GNUNET_TESTBED_Controller *c;
  1196. enum GNUNET_TESTBED_TopologyOption secondary_option;
  1197. if (num_peers < 2)
  1198. return NULL;
  1199. c = peers[0]->controller;
  1200. tc = GNUNET_new (struct TopologyContext);
  1201. tc->type = TOPOLOGYCONTEXT_TYPE_OVERLAY;
  1202. overlay = &tc->u.overlay;
  1203. overlay->peers = peers;
  1204. tc->num_peers = num_peers;
  1205. overlay->op_cls = op_cls;
  1206. overlay->retry_cnt = DEFAULT_RETRY_CNT;
  1207. overlay->comp_cb = comp_cb;
  1208. overlay->comp_cb_cls = comp_cb_cls;
  1209. switch (topo)
  1210. {
  1211. case GNUNET_TESTBED_TOPOLOGY_LINE:
  1212. gen_topo_line (tc);
  1213. break;
  1214. case GNUNET_TESTBED_TOPOLOGY_STAR:
  1215. gen_topo_star (tc);
  1216. break;
  1217. case GNUNET_TESTBED_TOPOLOGY_RING:
  1218. gen_topo_ring (tc);
  1219. break;
  1220. case GNUNET_TESTBED_TOPOLOGY_ERDOS_RENYI:
  1221. gen_topo_random (tc, va_arg (va, unsigned int), GNUNET_NO);
  1222. break;
  1223. case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD_RING:
  1224. gen_topo_ring (tc);
  1225. gen_topo_random (tc, va_arg (va, unsigned int), GNUNET_YES);
  1226. break;
  1227. case GNUNET_TESTBED_TOPOLOGY_CLIQUE:
  1228. gen_topo_clique (tc);
  1229. break;
  1230. case GNUNET_TESTBED_TOPOLOGY_2D_TORUS:
  1231. gen_topo_2dtorus (tc);
  1232. break;
  1233. case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD:
  1234. gen_topo_2dtorus (tc);
  1235. gen_topo_random (tc, va_arg (va, unsigned int), GNUNET_YES);
  1236. break;
  1237. case GNUNET_TESTBED_TOPOLOGY_SCALE_FREE:
  1238. {
  1239. uint16_t cap;
  1240. uint8_t m;
  1241. cap = (uint16_t) va_arg (va, unsigned int);
  1242. m = (uint8_t) va_arg (va, unsigned int);
  1243. gen_topo_scale_free (tc, cap, m);
  1244. }
  1245. break;
  1246. case GNUNET_TESTBED_TOPOLOGY_FROM_FILE:
  1247. {
  1248. const char *filename;
  1249. filename = va_arg (va, const char *);
  1250. GNUNET_assert (NULL != filename);
  1251. gen_topo_from_file (tc, filename);
  1252. }
  1253. break;
  1254. default:
  1255. GNUNET_break (0);
  1256. GNUNET_free (tc);
  1257. return NULL;
  1258. }
  1259. do
  1260. {
  1261. secondary_option = GNUNET_VA_ARG_ENUM (va, GNUNET_TESTBED_TopologyOption);
  1262. switch (secondary_option)
  1263. {
  1264. case GNUNET_TESTBED_TOPOLOGY_RETRY_CNT:
  1265. overlay->retry_cnt = va_arg (va, unsigned int);
  1266. break;
  1267. case GNUNET_TESTBED_TOPOLOGY_OPTION_END:
  1268. break;
  1269. default:
  1270. GNUNET_break (0); /* Should not use any other option apart from
  1271. * the ones handled here */
  1272. GNUNET_free_non_null (overlay->link_array);
  1273. GNUNET_free (tc);
  1274. return NULL;
  1275. }
  1276. }
  1277. while (GNUNET_TESTBED_TOPOLOGY_OPTION_END != secondary_option);
  1278. op = GNUNET_TESTBED_operation_create_ (tc,
  1279. &opstart_overlay_configure_topology,
  1280. &oprelease_overlay_configure_topology);
  1281. GNUNET_TESTBED_operation_queue_insert_
  1282. (c->opq_parallel_topology_config_operations, op);
  1283. GNUNET_TESTBED_operation_begin_wait_ (op);
  1284. LOG (GNUNET_ERROR_TYPE_DEBUG,
  1285. "Generated %u connections\n",
  1286. tc->link_array_size);
  1287. if (NULL != max_connections)
  1288. *max_connections = tc->link_array_size;
  1289. return op;
  1290. }
  1291. /**
  1292. * All peers must have been started before calling this function.
  1293. * This function then connects the given peers in the P2P overlay
  1294. * using the given topology.
  1295. *
  1296. * @param op_cls closure argument to give with the peer connect operation events
  1297. * generated through this function
  1298. * @param num_peers number of peers in 'peers'
  1299. * @param peers array of 'num_peers' with the peers to configure
  1300. * @param max_connections the maximums number of overlay connections that will
  1301. * be made to achieve the given topology
  1302. * @param comp_cb the completion callback to call when the topology generation
  1303. * is completed
  1304. * @param comp_cb_cls closure for the above completion callback
  1305. * @param topo desired underlay topology to use
  1306. * @param ... topology-specific options
  1307. * @return handle to the operation, NULL if connecting these
  1308. * peers is fundamentally not possible at this time (peers
  1309. * not running or underlay disallows) or if num_peers is less than 2
  1310. */
  1311. struct GNUNET_TESTBED_Operation *
  1312. GNUNET_TESTBED_overlay_configure_topology (void *op_cls,
  1313. unsigned int num_peers,
  1314. struct GNUNET_TESTBED_Peer **peers,
  1315. unsigned int *max_connections,
  1316. GNUNET_TESTBED_TopologyCompletionCallback
  1317. comp_cb,
  1318. void *comp_cb_cls,
  1319. enum GNUNET_TESTBED_TopologyOption
  1320. topo,
  1321. ...)
  1322. {
  1323. struct GNUNET_TESTBED_Operation *op;
  1324. va_list vargs;
  1325. GNUNET_assert (topo < GNUNET_TESTBED_TOPOLOGY_OPTION_END);
  1326. va_start (vargs, topo);
  1327. op = GNUNET_TESTBED_overlay_configure_topology_va (op_cls, num_peers, peers,
  1328. max_connections,
  1329. comp_cb, comp_cb_cls,
  1330. topo,
  1331. vargs);
  1332. va_end (vargs);
  1333. return op;
  1334. }
  1335. /**
  1336. * Get a topology from a string input.
  1337. *
  1338. * @param topology where to write the retrieved topology
  1339. * @param topology_string The string to attempt to
  1340. * get a configuration value from
  1341. * @return #GNUNET_YES if topology string matched a
  1342. * known topology, #GNUNET_NO if not
  1343. */
  1344. int
  1345. GNUNET_TESTBED_topology_get_ (enum GNUNET_TESTBED_TopologyOption *topology,
  1346. const char *topology_string)
  1347. {
  1348. unsigned int cnt;
  1349. for (cnt = 0; NULL != topology_strings[cnt]; cnt++)
  1350. {
  1351. if (0 == strcasecmp (topology_string, topology_strings[cnt]))
  1352. {
  1353. if (NULL != topology)
  1354. *topology = (enum GNUNET_TESTBED_TopologyOption) cnt;
  1355. GNUNET_assert (GNUNET_TESTBED_TOPOLOGY_OPTION_END !=
  1356. (enum GNUNET_TESTBED_TopologyOption) cnt);
  1357. return GNUNET_YES;
  1358. }
  1359. }
  1360. return GNUNET_NO;
  1361. }
  1362. /**
  1363. * Returns the string corresponding to the given topology
  1364. *
  1365. * @param topology the topology
  1366. * @return the string (freshly allocated) of given topology; NULL if topology cannot be
  1367. * expressed as a string
  1368. */
  1369. char *
  1370. GNUNET_TESTBED_topology_to_str_ (enum GNUNET_TESTBED_TopologyOption topology)
  1371. {
  1372. if (GNUNET_TESTBED_TOPOLOGY_OPTION_END <= topology)
  1373. return NULL;
  1374. return GNUNET_strdup (topology_strings[topology]);
  1375. }
  1376. /**
  1377. * Function to construct an underlay topology
  1378. *
  1379. * @param num_peers the number of peers for which the topology should be
  1380. * generated
  1381. * @param proc the underlay link processor callback. Will be called for each
  1382. * underlay link generated unless a previous call to this callback
  1383. * returned #GNUNET_SYSERR. Cannot be NULL.
  1384. * @param cls closure for @a proc
  1385. * @param ... variable arguments denoting the topology and its parameters. They
  1386. * should start with the type of topology to generate followed by their
  1387. * options.
  1388. * @return #GNUNET_OK if underlay link generation is successful; #GNUNET_SYSERR
  1389. * upon error in generating the underlay or if any calls to the
  1390. * underlay link processor returned #GNUNET_SYSERR
  1391. */
  1392. int
  1393. GNUNET_TESTBED_underlay_construct_ (int num_peers,
  1394. underlay_link_processor proc,
  1395. void *cls,
  1396. ...)
  1397. {
  1398. struct TopologyContext tc;
  1399. struct TopologyContextUnderlay *underlay;
  1400. struct UnderlayLink *ulink;
  1401. va_list vargs;
  1402. enum GNUNET_TESTBED_TopologyOption topology;
  1403. unsigned int cnt;
  1404. int ret;
  1405. GNUNET_assert (NULL != proc);
  1406. ret = GNUNET_OK;
  1407. memset (&tc, 0, sizeof(tc));
  1408. tc.num_peers = num_peers;
  1409. tc.type = TOPOLOGYCONTEXT_TYPE_UNDERLAY;
  1410. underlay = &tc.u.underlay;
  1411. va_start (vargs, cls);
  1412. topology = GNUNET_VA_ARG_ENUM (vargs, GNUNET_TESTBED_TopologyOption);
  1413. switch (topology)
  1414. {
  1415. case GNUNET_TESTBED_TOPOLOGY_LINE:
  1416. gen_topo_line (&tc);
  1417. break;
  1418. case GNUNET_TESTBED_TOPOLOGY_STAR:
  1419. gen_topo_star (&tc);
  1420. break;
  1421. case GNUNET_TESTBED_TOPOLOGY_RING:
  1422. gen_topo_ring (&tc);
  1423. break;
  1424. case GNUNET_TESTBED_TOPOLOGY_CLIQUE:
  1425. gen_topo_clique (&tc);
  1426. break;
  1427. case GNUNET_TESTBED_TOPOLOGY_2D_TORUS:
  1428. gen_topo_2dtorus (&tc);
  1429. break;
  1430. case GNUNET_TESTBED_TOPOLOGY_ERDOS_RENYI:
  1431. gen_topo_random (&tc, va_arg (vargs, unsigned int), GNUNET_NO);
  1432. break;
  1433. case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD_RING:
  1434. gen_topo_ring (&tc);
  1435. gen_topo_random (&tc, va_arg (vargs, unsigned int), GNUNET_YES);
  1436. break;
  1437. case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD:
  1438. gen_topo_2dtorus (&tc);
  1439. gen_topo_random (&tc, va_arg (vargs, unsigned int), GNUNET_YES);
  1440. break;
  1441. case GNUNET_TESTBED_TOPOLOGY_FROM_FILE:
  1442. {
  1443. const char *filename;
  1444. filename = va_arg (vargs, char *);
  1445. GNUNET_assert (NULL != filename);
  1446. gen_topo_from_file (&tc, filename);
  1447. }
  1448. break;
  1449. case GNUNET_TESTBED_TOPOLOGY_SCALE_FREE:
  1450. {
  1451. uint16_t cap;
  1452. uint8_t m;
  1453. cap = (uint16_t) va_arg (vargs, unsigned int);
  1454. m = (uint8_t) va_arg (vargs, unsigned int);
  1455. gen_topo_scale_free (&tc, cap, m);
  1456. }
  1457. break;
  1458. default:
  1459. GNUNET_assert (0);
  1460. }
  1461. va_end (vargs);
  1462. for (cnt = 0; cnt < tc.link_array_size; cnt++)
  1463. {
  1464. ulink = &underlay->link_array[cnt];
  1465. if (GNUNET_SYSERR == proc (cls,
  1466. ulink->A,
  1467. ulink->B,
  1468. ulink->bandwidth,
  1469. ulink->latency,
  1470. ulink->loss))
  1471. {
  1472. ret = GNUNET_SYSERR;
  1473. break;
  1474. }
  1475. }
  1476. GNUNET_free_non_null (underlay->link_array);
  1477. return ret;
  1478. }
  1479. /* end of testbed_api_topology.c */