1
0

SwitchCore.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  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 "memory/Allocator.h"
  16. #include "util/log/Log.h"
  17. #include "switch/SwitchCore.h"
  18. // TODO(cjd): Get rid of NumberCompress so we can set encodingScheme at runtime.
  19. #define NumberCompress_OLD_CODE
  20. #include "switch/NumberCompress.h"
  21. #include "switch/Penalty.h"
  22. #include "util/Bits.h"
  23. #include "util/Checksum.h"
  24. #include "util/Endian.h"
  25. #include "wire/Control.h"
  26. #include "wire/Error.h"
  27. #include "wire/Headers.h"
  28. #include "wire/SwitchHeader.h"
  29. #include "wire/Message.h"
  30. #include <inttypes.h>
  31. #include <stdbool.h>
  32. struct SwitchInterface
  33. {
  34. struct Iface iface;
  35. struct Allocator* alloc;
  36. struct SwitchCore_pvt* core;
  37. struct Penalty* penalty;
  38. struct Allocator_OnFreeJob* onFree;
  39. int state;
  40. Identity
  41. };
  42. struct SwitchCore_pvt
  43. {
  44. struct SwitchCore pub;
  45. struct SwitchInterface interfaces[NumberCompress_INTERFACES];
  46. bool routerAdded;
  47. struct Log* logger;
  48. struct EventBase* eventBase;
  49. struct Allocator* allocator;
  50. Identity
  51. };
  52. struct ErrorPacket8 {
  53. struct SwitchHeader switchHeader;
  54. uint32_t handle;
  55. struct Control ctrl;
  56. };
  57. Assert_compileTime(sizeof(struct ErrorPacket8) == SwitchHeader_SIZE + 4 + sizeof(struct Control));
  58. static inline Iface_DEFUN sendError(struct SwitchInterface* iface,
  59. struct Message* cause,
  60. uint32_t code,
  61. struct Log* logger)
  62. {
  63. if (cause->length < SwitchHeader_SIZE + 4) {
  64. Log_debug(logger, "runt");
  65. return NULL;
  66. }
  67. struct SwitchHeader* causeHeader = (struct SwitchHeader*) cause->bytes;
  68. if (SwitchHeader_getSuppressErrors(causeHeader)) {
  69. // don't send errors if they're asking us to suppress them!
  70. return NULL;
  71. }
  72. // limit of 256 bytes
  73. cause->length =
  74. (cause->length < Control_Error_MAX_SIZE) ? cause->length : Control_Error_MAX_SIZE;
  75. // Shift back so we can add another header.
  76. Message_push(cause,
  77. NULL,
  78. SwitchHeader_SIZE + 4 + Control_Header_SIZE + Control_Error_HEADER_SIZE,
  79. NULL);
  80. struct ErrorPacket8* err = (struct ErrorPacket8*) cause->bytes;
  81. err->switchHeader.label_be = Bits_bitReverse64(causeHeader->label_be);
  82. SwitchHeader_setSuppressErrors(&err->switchHeader, true);
  83. SwitchHeader_setVersion(&err->switchHeader, SwitchHeader_CURRENT_VERSION);
  84. SwitchHeader_setPenalty(&err->switchHeader, 0);
  85. SwitchHeader_setCongestion(&err->switchHeader, 0);
  86. err->handle = 0xffffffff;
  87. err->ctrl.header.type_be = Control_ERROR_be;
  88. err->ctrl.content.error.errorType_be = Endian_hostToBigEndian32(code);
  89. err->ctrl.header.checksum_be = 0;
  90. err->ctrl.header.checksum_be =
  91. Checksum_engine((uint8_t*) &err->ctrl, cause->length - SwitchHeader_SIZE - 4);
  92. return Iface_next(&iface->iface, cause);
  93. }
  94. #define DEBUG_SRC_DST(logger, message) \
  95. Log_debug(logger, message " ([%u] to [%u])", sourceIndex, destIndex)
  96. /** This never returns an error, it sends an error packet instead. */
  97. static Iface_DEFUN receiveMessage(struct Message* message, struct Iface* iface)
  98. {
  99. struct SwitchInterface* sourceIf = Identity_check((struct SwitchInterface*) iface);
  100. struct SwitchCore_pvt* core = Identity_check(sourceIf->core);
  101. if (message->length < SwitchHeader_SIZE) {
  102. Log_debug(core->logger, "DROP runt");
  103. return NULL;
  104. }
  105. struct SwitchHeader* header = (struct SwitchHeader*) message->bytes;
  106. const uint64_t label = Endian_bigEndianToHost64(header->label_be);
  107. uint32_t bits = NumberCompress_bitsUsedForLabel(label);
  108. const uint32_t sourceIndex = sourceIf - core->interfaces;
  109. const uint32_t destIndex = NumberCompress_getDecompressed(label, bits);
  110. const uint32_t sourceBits = NumberCompress_bitsUsedForNumber(sourceIndex);
  111. Assert_true(destIndex < NumberCompress_INTERFACES);
  112. Assert_true(sourceIndex < NumberCompress_INTERFACES);
  113. if (1 == destIndex && 1 != (label & 0xf)) {
  114. // routing interface: must always be compressed as 0001
  115. DEBUG_SRC_DST(core->logger,
  116. "DROP packet for this router because the destination "
  117. "discriminator was wrong");
  118. return sendError(sourceIf, message, Error_MALFORMED_ADDRESS, core->logger);
  119. }
  120. if (sourceBits > bits) {
  121. if (destIndex == 1) {
  122. // If the destination index is this router, don't drop the packet since there no
  123. // way for a node to know the size of the representation of its source label.
  124. // - label ends in 0001; if there are enough zeroes at the end after removing the 1,
  125. // we can still fit in the source discriminator
  126. // - the return path probably doesn't start with 3 zeroes, but it will still be working,
  127. // as the source discriminator is large enough to make space for 3 zeroes between
  128. // reverse return path and forward path (see below)
  129. if (0 != ((label ^ 1) & (UINT64_MAX >> (64 - sourceBits - 4)))) {
  130. // This is a bug.
  131. // https://github.com/cjdelisle/cjdns/issues/93
  132. // The problem is that there is no way to splice a route and know for certain
  133. // that you've not spliced one which will end up in this if statement.
  134. // Unfortunately there seems no clean way around this issue at the moment.
  135. // If this router and switch communicated using labels with "64 + four less
  136. // than the number of bits in largest discriminator" bits wide, it could handle
  137. // this situation, this solution is obviously non-trivial.
  138. DEBUG_SRC_DST(core->logger,
  139. "DROP packet for this router because there is no way to "
  140. "represent the return path.");
  141. return sendError(sourceIf, message, Error_RETURN_PATH_INVALID, core->logger);
  142. }
  143. bits = sourceBits;
  144. } else if (1 == sourceIndex) {
  145. // - we need at least 3 zeroes between reverse return path and forward path:
  146. // right now the label only contains the forward path
  147. // - sourceBits == 4, bits < 4 -> bits + 64 - sourceBits < 64
  148. // - the reverse source discriminator "1000" and the target discriminator "0001"
  149. // can overlap as "10001" (or "100001" or ...)
  150. if (0 != label >> (bits + 64 - sourceBits)) {
  151. // not enough zeroes
  152. DEBUG_SRC_DST(core->logger, "DROP packet because source address is "
  153. "larger than destination address.");
  154. return sendError(sourceIf, message, Error_MALFORMED_ADDRESS, core->logger);
  155. }
  156. } else {
  157. Log_info(core->logger, "source exceeds dest");
  158. DEBUG_SRC_DST(core->logger, "DROP packet because source address is "
  159. "larger than destination address.");
  160. return sendError(sourceIf, message, Error_MALFORMED_ADDRESS, core->logger);
  161. }
  162. }
  163. if (core->interfaces[destIndex].alloc == NULL) {
  164. Log_info(core->logger, "no such iface");
  165. DEBUG_SRC_DST(core->logger, "DROP packet because there is no interface "
  166. "where the bits specify.");
  167. return sendError(sourceIf, message, Error_MALFORMED_ADDRESS, core->logger);
  168. }
  169. if (core->interfaces[destIndex].state == SwitchCore_setInterfaceState_ifaceState_DOWN &&
  170. 1 != sourceIndex)
  171. {
  172. DEBUG_SRC_DST(core->logger, "DROP packet because interface is down");
  173. return sendError(sourceIf, message, Error_UNDELIVERABLE, core->logger);
  174. }
  175. /*if (sourceIndex == destIndex && sourceIndex != 1) {
  176. DEBUG_SRC_DST(core->logger, "DROP Packet with redundant route.");
  177. return sendError(sourceIf, message, Error_LOOP_ROUTE, core->logger);
  178. }*/
  179. uint64_t sourceLabel = Bits_bitReverse64(NumberCompress_getCompressed(sourceIndex, bits));
  180. uint64_t targetLabel = (label >> bits) | sourceLabel;
  181. int cloneLength = (message->length < Control_Error_MAX_SIZE) ?
  182. message->length : Control_Error_MAX_SIZE;
  183. uint8_t messageClone[Control_Error_MAX_SIZE];
  184. Bits_memcpy(messageClone, message->bytes, cloneLength);
  185. // Update the header
  186. header->label_be = Endian_hostToBigEndian64(targetLabel);
  187. uint32_t labelShift = SwitchHeader_getLabelShift(header) + bits;
  188. if (labelShift > 63) {
  189. // TODO(cjd): hmm should we return an error packet?
  190. Log_debug(core->logger, "Label rolled over");
  191. return NULL;
  192. }
  193. SwitchHeader_setLabelShift(header, labelShift);
  194. if (sourceIndex != 1 && destIndex != 1) {
  195. // no penalty for our own packets
  196. Penalty_apply(sourceIf->penalty, header, message->length);
  197. }
  198. return Iface_next(&core->interfaces[destIndex].iface, message);
  199. }
  200. static int removeInterface(struct Allocator_OnFreeJob* job)
  201. {
  202. struct SwitchInterface* si = Identity_check((struct SwitchInterface*) job->userData);
  203. Bits_memset(si, 0, sizeof(struct SwitchInterface));
  204. return 0;
  205. }
  206. void SwitchCore_setInterfaceState(struct Iface* userIf, int ifaceState)
  207. {
  208. struct SwitchInterface* sif = Identity_check((struct SwitchInterface*) userIf->connectedIf);
  209. Assert_true(ifaceState == (ifaceState & 1));
  210. sif->state = ifaceState;
  211. }
  212. void SwitchCore_swapInterfaces(struct Iface* userIf1, struct Iface* userIf2)
  213. {
  214. struct SwitchInterface* si1 = Identity_check((struct SwitchInterface*) userIf1->connectedIf);
  215. struct SwitchInterface* si2 = Identity_check((struct SwitchInterface*) userIf2->connectedIf);
  216. Iface_unplumb(userIf1, &si1->iface);
  217. Iface_unplumb(userIf2, &si2->iface);
  218. Assert_true(Allocator_cancelOnFree(si1->onFree) > -1);
  219. Assert_true(Allocator_cancelOnFree(si2->onFree) > -1);
  220. struct SwitchInterface si3;
  221. Bits_memcpy(&si3, si1, sizeof(struct SwitchInterface));
  222. Bits_memcpy(si1, si2, sizeof(struct SwitchInterface));
  223. Bits_memcpy(si2, &si3, sizeof(struct SwitchInterface));
  224. si1->onFree = Allocator_onFree(si1->alloc, removeInterface, si1);
  225. si2->onFree = Allocator_onFree(si2->alloc, removeInterface, si2);
  226. Iface_plumb(userIf2, &si1->iface);
  227. Iface_plumb(userIf1, &si2->iface);
  228. }
  229. int SwitchCore_addInterface(struct SwitchCore* switchCore,
  230. struct Iface* iface,
  231. struct Allocator* alloc,
  232. uint64_t* labelOut)
  233. {
  234. struct SwitchCore_pvt* core = Identity_check((struct SwitchCore_pvt*)switchCore);
  235. int ifIndex = 0;
  236. // If there's a vacent spot where another iface was before it was removed, use that.
  237. for (;;ifIndex++) {
  238. if (!core->interfaces[ifIndex].iface.send) { break; }
  239. if (ifIndex == NumberCompress_INTERFACES) { return SwitchCore_addInterface_OUT_OF_SPACE; }
  240. }
  241. struct SwitchInterface* newIf = &core->interfaces[ifIndex];
  242. Identity_set(newIf);
  243. newIf->iface.send = receiveMessage;
  244. newIf->core = core;
  245. newIf->alloc = alloc;
  246. newIf->penalty = Penalty_new(alloc, core->eventBase, core->logger);
  247. newIf->onFree = Allocator_onFree(alloc, removeInterface, newIf);
  248. newIf->state = SwitchCore_setInterfaceState_ifaceState_UP;
  249. Iface_plumb(iface, &newIf->iface);
  250. uint32_t bits = NumberCompress_bitsUsedForNumber(ifIndex);
  251. *labelOut = NumberCompress_getCompressed(ifIndex, bits) | (1 << bits);
  252. return 0;
  253. }
  254. struct SwitchCore* SwitchCore_new(struct Log* logger,
  255. struct Allocator* allocator,
  256. struct EventBase* base)
  257. {
  258. struct SwitchCore_pvt* core = Allocator_calloc(allocator, sizeof(struct SwitchCore_pvt), 1);
  259. Identity_set(core);
  260. core->allocator = allocator;
  261. core->logger = logger;
  262. core->eventBase = base;
  263. struct SwitchInterface* routerIf = &core->interfaces[1];
  264. Identity_set(routerIf);
  265. routerIf->iface.send = receiveMessage;
  266. routerIf->core = core;
  267. routerIf->alloc = allocator;
  268. routerIf->state = SwitchCore_setInterfaceState_ifaceState_UP;
  269. core->pub.routerIf = &routerIf->iface;
  270. return &core->pub;
  271. }