Benchmark.c 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  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 <http://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 "interface/Iface.h"
  20. #include "util/log/FileWriterLog.h"
  21. #include "util/events/Time.h"
  22. #include "util/events/Timeout.h"
  23. #include "net/NetCore.h"
  24. #include "util/Checksum.h"
  25. struct Context
  26. {
  27. struct Allocator* alloc;
  28. struct EventBase* base;
  29. struct Log* log;
  30. struct Random* rand;
  31. uint64_t startTime;
  32. uint64_t items;
  33. char* benchName;
  34. char* itemName;
  35. Identity
  36. };
  37. static void begin(struct Context* ctx, char* benchName, uint64_t items, char* itemName)
  38. {
  39. Assert_true(!ctx->benchName);
  40. ctx->benchName = benchName;
  41. ctx->itemName = itemName;
  42. ctx->items = items;
  43. Log_info(ctx->log, "----- Begin %s benchmark -----", benchName);
  44. ctx->startTime = Time_hrtime();
  45. }
  46. static void done(struct Context* ctx)
  47. {
  48. uint64_t endTimes = Time_hrtime();
  49. uint64_t time = (endTimes - ctx->startTime) / 1000000;
  50. // same as items / (time / 1024) (converting time to seconds)
  51. uint64_t kbps = (ctx->items * 1024) / time;
  52. Log_info(ctx->log, " ");
  53. Log_info(ctx->log, "---------------------------------------------------------------");
  54. Log_info(ctx->log, "Benchmark %s in %dms. %d %s per second",
  55. ctx->benchName, (int)time, (int)kbps, ctx->itemName);
  56. Log_info(ctx->log, "---------------------------------------------------------------");
  57. Log_info(ctx->log, " ");
  58. Assert_true(ctx->benchName);
  59. ctx->benchName = NULL;
  60. }
  61. static void cryptoAuth(struct Context* ctx)
  62. {
  63. Log_info(ctx->log, "Setting up salsa20/poly1305 benchmark (encryption and decryption only)");
  64. struct Allocator* alloc = Allocator_child(ctx->alloc);
  65. struct CryptoAuth* ca1 = CryptoAuth_new(alloc, NULL, ctx->base, ctx->log, ctx->rand);
  66. struct CryptoAuth* ca2 = CryptoAuth_new(alloc, NULL, ctx->base, ctx->log, ctx->rand);
  67. struct CryptoAuth_Session* sess1 =
  68. CryptoAuth_newSession(ca1, alloc, ca2->publicKey, NULL, false, "bench");
  69. struct CryptoAuth_Session* sess2 =
  70. CryptoAuth_newSession(ca2, alloc, ca1->publicKey, NULL, false, "bench");
  71. int size = 1500;
  72. int count = 100000;
  73. struct Message* msg = Message_new(size, 256, alloc);
  74. Random_bytes(ctx->rand, msg->bytes, msg->length);
  75. // setup session
  76. for (int i = 0; i < 2; i++) {
  77. Assert_true(!CryptoAuth_encrypt(sess1, msg));
  78. Assert_true(!CryptoAuth_decrypt(sess2, msg));
  79. Assert_true(!CryptoAuth_encrypt(sess2, msg));
  80. Assert_true(!CryptoAuth_decrypt(sess1, msg));
  81. }
  82. begin(ctx, "salsa20/poly1305", (count * size * 8) / 1024, "kilobits");
  83. for (int i = 0; i < count; i++) {
  84. Assert_true(!CryptoAuth_encrypt(sess1, msg));
  85. Assert_true(!CryptoAuth_decrypt(sess2, msg));
  86. }
  87. done(ctx);
  88. Allocator_free(alloc);
  89. }
  90. struct SwitchingContext
  91. {
  92. struct Iface aliceIf;
  93. struct Iface bobIf;
  94. struct Context* benchmarkCtx;
  95. struct Iface aliceCtrlIf;
  96. int msgCount;
  97. Identity
  98. };
  99. static Iface_DEFUN aliceToBob(struct Message* msg, struct Iface* aliceIf)
  100. {
  101. struct SwitchingContext* sc =
  102. Identity_containerOf(aliceIf, struct SwitchingContext, aliceIf);
  103. return Iface_next(&sc->bobIf, msg);
  104. }
  105. static Iface_DEFUN bobToAlice(struct Message* msg, struct Iface* bobIf)
  106. {
  107. struct SwitchingContext* sc =
  108. Identity_containerOf(bobIf, struct SwitchingContext, bobIf);
  109. return Iface_next(&sc->aliceIf, msg);
  110. }
  111. static Iface_DEFUN aliceCtrlRecv(struct Message* msg, struct Iface* aliceCtrlIf)
  112. {
  113. struct SwitchingContext* sc =
  114. Identity_containerOf(aliceCtrlIf, struct SwitchingContext, aliceCtrlIf);
  115. //Log_debug(sc->benchmarkCtx->log, "pong!");
  116. sc->msgCount++;
  117. return NULL;
  118. }
  119. #define SECRETA \
  120. "\xd8\x54\x3e\x70\xb9\xae\x7c\x41\xbc\x18\xa4\x9a\x9c\xee\xca\x9c" \
  121. "\xdc\x45\x01\x96\x6b\xbd\x7e\x76\xcf\x3a\x9f\xbc\x12\xed\x8b\xb4"
  122. #define SECRETB \
  123. "\xad\x7e\xa3\x26\xaa\x01\x94\x0a\x25\xbc\x9e\x01\x26\x22\xdb\x69" \
  124. "\x4f\xd9\xb4\x17\x7c\xf3\xf8\x91\x16\xf3\xcf\xe8\x5c\x80\xe1\x4a"
  125. static void switching(struct Context* ctx)
  126. {
  127. Log_info(ctx->log, "Setting up salsa20/poly1305 benchmark (encryption and decryption only)");
  128. struct Allocator* alloc = Allocator_child(ctx->alloc);;
  129. struct SwitchingContext* sc = Allocator_calloc(alloc, sizeof(struct SwitchingContext), 1);
  130. Identity_set(sc);
  131. sc->benchmarkCtx = ctx;
  132. sc->aliceIf.send = aliceToBob;
  133. sc->bobIf.send = bobToAlice;
  134. sc->aliceCtrlIf.send = aliceCtrlRecv;
  135. struct NetCore* alice = NetCore_new(SECRETA, alloc, ctx->base, ctx->rand, ctx->log);
  136. struct InterfaceController_Iface* aliceIci =
  137. InterfaceController_newIface(alice->ifController, String_CONST("alice"), alloc);
  138. Iface_plumb(&sc->aliceIf, &aliceIci->addrIf);
  139. struct NetCore* bob = NetCore_new(SECRETB, alloc, ctx->base, ctx->rand, ctx->log);
  140. struct InterfaceController_Iface* bobIci =
  141. InterfaceController_newIface(bob->ifController, String_CONST("bob"), alloc);
  142. Iface_plumb(&sc->bobIf, &bobIci->addrIf);
  143. CryptoAuth_addUser(String_CONST("abcdefg123"), String_CONST("TEST"), bob->ca);
  144. // Client has pubKey and passwd for the server.
  145. int ret = InterfaceController_bootstrapPeer(alice->ifController,
  146. aliceIci->ifNum,
  147. bob->ca->publicKey,
  148. Sockaddr_LOOPBACK,
  149. String_CONST("abcdefg123"),
  150. NULL,
  151. NULL,
  152. alloc);
  153. Assert_true(!ret);
  154. Iface_unplumb(alice->switchAdapter->controlIf.connectedIf, &alice->switchAdapter->controlIf);
  155. Iface_plumb(&alice->switchAdapter->controlIf, &sc->aliceCtrlIf);
  156. struct Message* msg = Message_new(Control_Ping_MIN_SIZE + Control_Header_SIZE, 256, alloc);
  157. struct Control_Header* ch = (struct Control_Header*) msg->bytes;
  158. struct Control_Ping* ping = (struct Control_Ping*) &ch[1];
  159. ping->version_be = Endian_hostToBigEndian32(Version_CURRENT_PROTOCOL);
  160. Message_push32(msg, 0xffffffff, NULL);
  161. uint32_t* handle_be = (uint32_t*)msg->bytes;
  162. Message_push(msg, NULL, SwitchHeader_SIZE, NULL);
  163. struct SwitchHeader* sh = (struct SwitchHeader*) msg->bytes;
  164. // TODO(cjd): this will fail with a different encoding scheme
  165. sh->label_be = Endian_hostToBigEndian64(0x13);
  166. for (int i = 1; i < 6; i++) {
  167. ping->magic = Control_Ping_MAGIC;
  168. ch->type_be = Control_PING_be;
  169. ch->checksum_be = 0;
  170. ch->checksum_be = Checksum_engine((void*)ch, Control_Ping_MIN_SIZE + Control_Header_SIZE);
  171. Iface_send(&sc->aliceCtrlIf, msg);
  172. Assert_true(sc->msgCount == i);
  173. Assert_true(msg->bytes == (void*)sh);
  174. Assert_true(ping->magic == Control_Pong_MAGIC);
  175. Assert_true(ch->type_be = Control_PONG_be);
  176. Assert_true(!Checksum_engine((void*)ch, Control_Ping_MIN_SIZE + Control_Header_SIZE));
  177. }
  178. *handle_be = 0xfffffff0;
  179. int count = 1000000;
  180. begin(ctx, "Switching", count, "packets");
  181. for (int i = 0; i < count; i++) {
  182. sh->versionAndLabelShift = SwitchHeader_CURRENT_VERSION << 6;
  183. Iface_send(&sc->aliceCtrlIf, msg);
  184. Assert_true(msg->bytes == (void*)sh);
  185. }
  186. done(ctx);
  187. Log_info(ctx->log, "DONE");
  188. Allocator_free(alloc);
  189. }
  190. /** Check if nodes A and C can communicate via B without A knowing that C exists. */
  191. void Benchmark_runAll()
  192. {
  193. struct Allocator* alloc = MallocAllocator_new(1<<22);
  194. struct Context* ctx = Allocator_calloc(alloc, sizeof(struct Context), 1);
  195. Identity_set(ctx);
  196. ctx->alloc = alloc;
  197. ctx->base = EventBase_new(alloc);
  198. struct Log* log = ctx->log = FileWriterLog_new(stdout, alloc);
  199. ctx->rand = Random_new(alloc, log, NULL);
  200. cryptoAuth(ctx);
  201. switching(ctx);
  202. }