Benchmark.c 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. /* vim: set expandtab ts=4 sw=4: */
  2. /*
  3. * You may redistribute this program and/or modify it under the terms of
  4. * the GNU General Public License as published by the Free Software Foundation,
  5. * either version 3 of the License, or (at your option) any later version.
  6. *
  7. * This program is distributed in the hope that it will be useful,
  8. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. * GNU General Public License for more details.
  11. *
  12. * You should have received a copy of the GNU General Public License
  13. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  14. */
  15. #include "net/Benchmark.h"
  16. #include "memory/MallocAllocator.h"
  17. #include "memory/Allocator.h"
  18. #include "crypto/random/Random.h"
  19. #include "crypto/Key.h"
  20. #include "interface/Iface.h"
  21. #include "util/log/FileWriterLog.h"
  22. #include "util/events/Time.h"
  23. #include "util/events/Timeout.h"
  24. #include "net/NetCore.h"
  25. #include "util/Checksum.h"
  26. struct Context
  27. {
  28. struct Allocator* alloc;
  29. struct EventBase* base;
  30. struct Log* log;
  31. struct Random* rand;
  32. uint64_t startTime;
  33. uint64_t items;
  34. char* benchName;
  35. char* itemName;
  36. Identity
  37. };
  38. static void begin(struct Context* ctx, char* benchName, uint64_t items, char* itemName)
  39. {
  40. Assert_true(!ctx->benchName);
  41. ctx->benchName = benchName;
  42. ctx->itemName = itemName;
  43. ctx->items = items;
  44. Log_info(ctx->log, "----- Begin %s benchmark -----", benchName);
  45. ctx->startTime = Time_hrtime();
  46. }
  47. static void done(struct Context* ctx)
  48. {
  49. uint64_t endTimes = Time_hrtime();
  50. uint64_t time = (endTimes - ctx->startTime) / 1000000;
  51. // same as items / (time / 1024) (converting time to seconds)
  52. uint64_t kbps = (ctx->items * 1024) / time;
  53. Log_info(ctx->log, " ");
  54. Log_info(ctx->log, "---------------------------------------------------------------");
  55. Log_info(ctx->log, "Benchmark %s in %dms. %d %s per second",
  56. ctx->benchName, (int)time, (int)kbps, ctx->itemName);
  57. Log_info(ctx->log, "---------------------------------------------------------------");
  58. Log_info(ctx->log, " ");
  59. Assert_true(ctx->benchName);
  60. ctx->benchName = NULL;
  61. }
  62. static void cryptoAuth(struct Context* ctx)
  63. {
  64. Log_info(ctx->log, "Setting up salsa20/poly1305 benchmark (encryption and decryption only)");
  65. struct Allocator* alloc = Allocator_child(ctx->alloc);
  66. struct CryptoAuth* ca1 = CryptoAuth_new(alloc, NULL, ctx->base, ctx->log, ctx->rand);
  67. struct CryptoAuth* ca2 = CryptoAuth_new(alloc, NULL, ctx->base, ctx->log, ctx->rand);
  68. struct CryptoAuth_Session* sess1 =
  69. CryptoAuth_newSession(ca1, alloc, ca2->publicKey, false, "bench");
  70. struct CryptoAuth_Session* sess2 =
  71. CryptoAuth_newSession(ca2, alloc, ca1->publicKey, false, "bench");
  72. int size = 1500;
  73. int count = 100000;
  74. struct Message* msg = Message_new(size, 256, alloc);
  75. Random_bytes(ctx->rand, msg->bytes, msg->length);
  76. // setup session
  77. for (int i = 0; i < 2; i++) {
  78. Assert_true(!CryptoAuth_encrypt(sess1, msg));
  79. Assert_true(!CryptoAuth_decrypt(sess2, msg));
  80. Assert_true(!CryptoAuth_encrypt(sess2, msg));
  81. Assert_true(!CryptoAuth_decrypt(sess1, msg));
  82. }
  83. begin(ctx, "salsa20/poly1305", (count * size * 8) / 1024, "kilobits");
  84. for (int i = 0; i < count; i++) {
  85. Assert_true(!CryptoAuth_encrypt(sess1, msg));
  86. Assert_true(!CryptoAuth_decrypt(sess2, msg));
  87. }
  88. done(ctx);
  89. Allocator_free(alloc);
  90. }
  91. struct SwitchingContext
  92. {
  93. struct Iface aliceIf;
  94. struct Iface bobIf;
  95. struct Context* benchmarkCtx;
  96. struct Iface aliceCtrlIf;
  97. int msgCount;
  98. Identity
  99. };
  100. static Iface_DEFUN aliceToBob(struct Message* msg, struct Iface* aliceIf)
  101. {
  102. struct SwitchingContext* sc =
  103. Identity_containerOf(aliceIf, struct SwitchingContext, aliceIf);
  104. return Iface_next(&sc->bobIf, msg);
  105. }
  106. static Iface_DEFUN bobToAlice(struct Message* msg, struct Iface* bobIf)
  107. {
  108. struct SwitchingContext* sc =
  109. Identity_containerOf(bobIf, struct SwitchingContext, bobIf);
  110. return Iface_next(&sc->aliceIf, msg);
  111. }
  112. static Iface_DEFUN aliceCtrlRecv(struct Message* msg, struct Iface* aliceCtrlIf)
  113. {
  114. struct SwitchingContext* sc =
  115. Identity_containerOf(aliceCtrlIf, struct SwitchingContext, aliceCtrlIf);
  116. //Log_debug(sc->benchmarkCtx->log, "pong!");
  117. sc->msgCount++;
  118. return NULL;
  119. }
  120. static void switching(struct Context* ctx)
  121. {
  122. Log_info(ctx->log, "Setting up salsa20/poly1305 benchmark (encryption and decryption only)");
  123. struct Allocator* alloc = Allocator_child(ctx->alloc);;
  124. uint8_t ipv6[16];
  125. uint8_t publicKey[32];
  126. uint8_t privateKeyA[32];
  127. uint8_t privateKeyB[32];
  128. Key_gen(ipv6, publicKey, privateKeyA, ctx->rand);
  129. Key_gen(ipv6, publicKey, privateKeyB, ctx->rand);
  130. struct SwitchingContext* sc = Allocator_calloc(alloc, sizeof(struct SwitchingContext), 1);
  131. Identity_set(sc);
  132. sc->benchmarkCtx = ctx;
  133. sc->aliceIf.send = aliceToBob;
  134. sc->bobIf.send = bobToAlice;
  135. sc->aliceCtrlIf.send = aliceCtrlRecv;
  136. struct NetCore* alice = NetCore_new(privateKeyA, alloc, ctx->base, ctx->rand, ctx->log);
  137. struct InterfaceController_Iface* aliceIci =
  138. InterfaceController_newIface(alice->ifController, String_CONST("alice"), alloc);
  139. Iface_plumb(&sc->aliceIf, &aliceIci->addrIf);
  140. struct NetCore* bob = NetCore_new(privateKeyB, alloc, ctx->base, ctx->rand, ctx->log);
  141. struct InterfaceController_Iface* bobIci =
  142. InterfaceController_newIface(bob->ifController, String_CONST("bob"), alloc);
  143. Iface_plumb(&sc->bobIf, &bobIci->addrIf);
  144. CryptoAuth_addUser(String_CONST("abcdefg123"), String_CONST("TEST"), bob->ca);
  145. // Client has pubKey and passwd for the server.
  146. int ret = InterfaceController_bootstrapPeer(alice->ifController,
  147. aliceIci->ifNum,
  148. bob->ca->publicKey,
  149. Sockaddr_LOOPBACK,
  150. String_CONST("abcdefg123"),
  151. NULL,
  152. NULL,
  153. alloc);
  154. Assert_true(!ret);
  155. Iface_unplumb(alice->upper->controlHandlerIf.connectedIf,
  156. &alice->upper->controlHandlerIf);
  157. Iface_plumb(&alice->upper->controlHandlerIf, &sc->aliceCtrlIf);
  158. struct Message* msg = Message_new(Control_Ping_MIN_SIZE + Control_Header_SIZE, 256, alloc);
  159. struct Control_Header* ch = (struct Control_Header*) msg->bytes;
  160. struct Control_Ping* ping = (struct Control_Ping*) &ch[1];
  161. ping->version_be = Endian_hostToBigEndian32(Version_CURRENT_PROTOCOL);
  162. Er_assert(Message_epush(msg, NULL, RouteHeader_SIZE));
  163. struct RouteHeader* rh = (struct RouteHeader*) msg->bytes;
  164. // TODO(cjd): this will fail with a different encoding scheme
  165. rh->sh.label_be = Endian_hostToBigEndian64(0x13);
  166. rh->flags |= RouteHeader_flags_CTRLMSG;
  167. int count = 100000;
  168. // This is the easiest way to represent that the packet does out and back
  169. // so it should be double counted in "packets per second".
  170. begin(ctx, "Switching", count * 2, "packets");
  171. for (int i = 1; i < count; i++) {
  172. rh->flags &= ~RouteHeader_flags_INCOMING;
  173. ping->magic = Control_Ping_MAGIC;
  174. ch->type_be = Control_PING_be;
  175. ch->checksum_be = 0;
  176. ch->checksum_be = Checksum_engine((void*)ch, Control_Ping_MIN_SIZE + Control_Header_SIZE);
  177. Iface_send(&sc->aliceCtrlIf, msg);
  178. Assert_true(msg->bytes == (void*)rh);
  179. Assert_true(sc->msgCount == i);
  180. Assert_true(ping->magic == Control_Pong_MAGIC);
  181. Assert_true(ch->type_be = Control_PONG_be);
  182. Assert_true(!Checksum_engine((void*)ch, Control_Ping_MIN_SIZE + Control_Header_SIZE));
  183. }
  184. done(ctx);
  185. Log_info(ctx->log, "DONE");
  186. Allocator_free(alloc);
  187. }
  188. /** Check if nodes A and C can communicate via B without A knowing that C exists. */
  189. void Benchmark_runAll(void)
  190. {
  191. struct Allocator* alloc = MallocAllocator_new(1<<22);
  192. struct Context* ctx = Allocator_calloc(alloc, sizeof(struct Context), 1);
  193. Identity_set(ctx);
  194. ctx->alloc = alloc;
  195. ctx->base = EventBase_new(alloc);
  196. struct Log* log = ctx->log = FileWriterLog_new(stdout, alloc);
  197. ctx->rand = Random_new(alloc, log, NULL);
  198. cryptoAuth(ctx);
  199. switching(ctx);
  200. }