SwitchCore.c 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  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 "util/Bits.h"
  22. #include "util/Checksum.h"
  23. #include "util/Endian.h"
  24. #include "wire/Control.h"
  25. #include "wire/Error.h"
  26. #include "wire/Headers.h"
  27. #include "wire/SwitchHeader.h"
  28. #include "wire/Message.h"
  29. #include <inttypes.h>
  30. #include <stdbool.h>
  31. struct SwitchInterface
  32. {
  33. struct Iface iface;
  34. struct Allocator* alloc;
  35. struct SwitchCore_pvt* core;
  36. struct Allocator_OnFreeJob* onFree;
  37. int state;
  38. Identity
  39. };
  40. struct SwitchCore_pvt
  41. {
  42. struct SwitchCore pub;
  43. struct SwitchInterface routerIf;
  44. struct SwitchInterface interfaces[NumberCompress_INTERFACES];
  45. bool routerAdded;
  46. struct Log* logger;
  47. struct EventBase* eventBase;
  48. struct Allocator* allocator;
  49. Identity
  50. };
  51. struct ErrorPacket8 {
  52. struct SwitchHeader switchHeader;
  53. uint32_t handle;
  54. struct Control ctrl;
  55. };
  56. Assert_compileTime(sizeof(struct ErrorPacket8) == SwitchHeader_SIZE + 4 + sizeof(struct Control));
  57. static inline Iface_DEFUN sendError(struct SwitchInterface* iface,
  58. struct Message* cause,
  59. uint32_t code,
  60. struct Log* logger)
  61. {
  62. if (cause->length < SwitchHeader_SIZE + 4) {
  63. Log_debug(logger, "runt");
  64. return NULL;
  65. }
  66. struct SwitchHeader* causeHeader = (struct SwitchHeader*) cause->bytes;
  67. if (SwitchHeader_getSuppressErrors(causeHeader)) {
  68. // don't send errors if they're asking us to suppress them!
  69. return NULL;
  70. }
  71. // limit of 256 bytes
  72. cause->length =
  73. (cause->length < Control_Error_MAX_SIZE) ? cause->length : Control_Error_MAX_SIZE;
  74. // Shift back so we can add another header.
  75. Message_push(cause,
  76. NULL,
  77. SwitchHeader_SIZE + 4 + Control_Header_SIZE + Control_Error_HEADER_SIZE,
  78. NULL);
  79. struct ErrorPacket8* err = (struct ErrorPacket8*) cause->bytes;
  80. err->switchHeader.label_be = Bits_bitReverse64(causeHeader->label_be);
  81. SwitchHeader_setSuppressErrors(&err->switchHeader, true);
  82. SwitchHeader_setVersion(&err->switchHeader, SwitchHeader_CURRENT_VERSION);
  83. SwitchHeader_setTrafficClass(&err->switchHeader, 0xffff);
  84. SwitchHeader_setCongestion(&err->switchHeader, 0);
  85. err->handle = 0xffffffff;
  86. err->ctrl.header.type_be = Control_ERROR_be;
  87. err->ctrl.content.error.errorType_be = Endian_hostToBigEndian32(code);
  88. err->ctrl.header.checksum_be = 0;
  89. err->ctrl.header.checksum_be =
  90. Checksum_engine((uint8_t*) &err->ctrl, cause->length - SwitchHeader_SIZE - 4);
  91. return Iface_next(&iface->iface, cause);
  92. }
  93. #define DEBUG_SRC_DST(logger, message) \
  94. Log_debug(logger, message " ([%d] to [%u])", sourceIdx, destIdx)
  95. /** This never returns an error, it sends an error packet instead. */
  96. static Iface_DEFUN receiveMessage(struct Message* message, struct Iface* iface)
  97. {
  98. struct SwitchInterface* sourceIf = Identity_check((struct SwitchInterface*) iface);
  99. struct SwitchCore_pvt* core = Identity_check(sourceIf->core);
  100. if (message->length < SwitchHeader_SIZE) {
  101. Log_debug(core->logger, "DROP runt");
  102. return NULL;
  103. }
  104. struct SwitchHeader* header = (struct SwitchHeader*) message->bytes;
  105. const uint64_t label = Endian_bigEndianToHost64(header->label_be);
  106. const uint32_t bits = NumberCompress_bitsUsedForLabel(label);
  107. const uint32_t labelShift = SwitchHeader_getLabelShift(header);
  108. int sourceIdx;
  109. uint64_t sourceLabel;
  110. if (sourceIf == &core->routerIf) {
  111. // message coming from us
  112. sourceIdx = -1;
  113. sourceLabel = Bits_bitReverse64(1);
  114. } else {
  115. sourceIdx = sourceIf - core->interfaces;
  116. sourceLabel = Bits_bitReverse64(NumberCompress_getCompressed(sourceIdx, bits));
  117. }
  118. int destIdx;
  119. struct SwitchInterface* destIf = NULL;
  120. if ((label << labelShift >> labelShift) == 1) {
  121. // There is only 0001 or 0000 left after getting rid of the bits
  122. // which come from revere paths, therefore the packet must be destine for us
  123. // See: Version.h (21)
  124. destIdx = -1;
  125. destIf = &core->routerIf;
  126. } else {
  127. destIdx = NumberCompress_getDecompressed(label, bits);
  128. destIf = &core->interfaces[destIdx];
  129. if (core->interfaces[destIdx].alloc == NULL) {
  130. DEBUG_SRC_DST(core->logger, "DROP no interface where bits specify");
  131. return sendError(sourceIf, message, Error_MALFORMED_ADDRESS, core->logger);
  132. }
  133. if (core->interfaces[destIdx].state == SwitchCore_setInterfaceState_ifaceState_DOWN &&
  134. -1 != sourceIdx)
  135. {
  136. DEBUG_SRC_DST(core->logger, "DROP interface is down");
  137. return sendError(sourceIf, message, Error_UNDELIVERABLE, core->logger);
  138. }
  139. }
  140. if (sourceIdx > -1 && NumberCompress_bitsUsedForNumber(sourceIdx) > bits) {
  141. DEBUG_SRC_DST(core->logger,
  142. "DROP packet because source address is larger than destination address.");
  143. return sendError(sourceIf, message, Error_MALFORMED_ADDRESS, core->logger);
  144. }
  145. uint64_t targetLabel = (label >> bits) | sourceLabel;
  146. int cloneLength = (message->length < Control_Error_MAX_SIZE) ?
  147. message->length : Control_Error_MAX_SIZE;
  148. uint8_t messageClone[Control_Error_MAX_SIZE];
  149. Bits_memcpy(messageClone, message->bytes, cloneLength);
  150. // Update the header
  151. header->label_be = Endian_hostToBigEndian64(targetLabel);
  152. if (labelShift + bits > 63) {
  153. // TODO(cjd): hmm should we return an error packet?
  154. Log_debug(core->logger, "Label rolled over");
  155. return NULL;
  156. }
  157. SwitchHeader_setLabelShift(header, labelShift + bits);
  158. SwitchHeader_setTrafficClass(header, 0xffff);
  159. return Iface_next(&destIf->iface, message);
  160. }
  161. static int removeInterface(struct Allocator_OnFreeJob* job)
  162. {
  163. struct SwitchInterface* si = Identity_check((struct SwitchInterface*) job->userData);
  164. Bits_memset(si, 0, sizeof(struct SwitchInterface));
  165. return 0;
  166. }
  167. void SwitchCore_setInterfaceState(struct Iface* userIf, int ifaceState)
  168. {
  169. struct SwitchInterface* sif = Identity_check((struct SwitchInterface*) userIf->connectedIf);
  170. Assert_true(ifaceState == (ifaceState & 1));
  171. sif->state = ifaceState;
  172. }
  173. void SwitchCore_swapInterfaces(struct Iface* userIf1, struct Iface* userIf2)
  174. {
  175. struct SwitchInterface* si1 = Identity_check((struct SwitchInterface*) userIf1->connectedIf);
  176. struct SwitchInterface* si2 = Identity_check((struct SwitchInterface*) userIf2->connectedIf);
  177. Iface_unplumb(userIf1, &si1->iface);
  178. Iface_unplumb(userIf2, &si2->iface);
  179. Assert_true(Allocator_cancelOnFree(si1->onFree) > -1);
  180. Assert_true(Allocator_cancelOnFree(si2->onFree) > -1);
  181. struct SwitchInterface si3;
  182. Bits_memcpy(&si3, si1, sizeof(struct SwitchInterface));
  183. Bits_memcpy(si1, si2, sizeof(struct SwitchInterface));
  184. Bits_memcpy(si2, &si3, sizeof(struct SwitchInterface));
  185. si1->onFree = Allocator_onFree(si1->alloc, removeInterface, si1);
  186. si2->onFree = Allocator_onFree(si2->alloc, removeInterface, si2);
  187. Iface_plumb(userIf2, &si1->iface);
  188. Iface_plumb(userIf1, &si2->iface);
  189. }
  190. int SwitchCore_addInterface(struct SwitchCore* switchCore,
  191. struct Iface* iface,
  192. struct Allocator* alloc,
  193. uint64_t* labelOut)
  194. {
  195. struct SwitchCore_pvt* core = Identity_check((struct SwitchCore_pvt*)switchCore);
  196. int ifIndex = 0;
  197. // If there's a vacent spot where another iface was before it was removed, use that.
  198. for (;;ifIndex++) {
  199. if (!core->interfaces[ifIndex].iface.send) { break; }
  200. if (ifIndex == NumberCompress_INTERFACES) { return SwitchCore_addInterface_OUT_OF_SPACE; }
  201. }
  202. struct SwitchInterface* newIf = &core->interfaces[ifIndex];
  203. Identity_set(newIf);
  204. newIf->iface.send = receiveMessage;
  205. newIf->core = core;
  206. newIf->alloc = alloc;
  207. newIf->onFree = Allocator_onFree(alloc, removeInterface, newIf);
  208. newIf->state = SwitchCore_setInterfaceState_ifaceState_UP;
  209. Iface_plumb(iface, &newIf->iface);
  210. uint32_t bits = NumberCompress_bitsUsedForNumber(ifIndex);
  211. *labelOut = NumberCompress_getCompressed(ifIndex, bits) | (1 << bits);
  212. return 0;
  213. }
  214. struct SwitchCore* SwitchCore_new(struct Log* logger,
  215. struct Allocator* allocator,
  216. struct EventBase* base)
  217. {
  218. struct SwitchCore_pvt* core = Allocator_calloc(allocator, sizeof(struct SwitchCore_pvt), 1);
  219. Identity_set(core);
  220. core->allocator = allocator;
  221. core->logger = logger;
  222. core->eventBase = base;
  223. struct SwitchInterface* routerIf = &core->routerIf;
  224. Identity_set(routerIf);
  225. routerIf->iface.send = receiveMessage;
  226. routerIf->core = core;
  227. routerIf->alloc = allocator;
  228. routerIf->state = SwitchCore_setInterfaceState_ifaceState_UP;
  229. core->pub.routerIf = &routerIf->iface;
  230. return &core->pub;
  231. }