EncodingScheme.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513
  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 "benc/String.h"
  16. #include "benc/Dict.h"
  17. #include "benc/List.h"
  18. #include "memory/Allocator.h"
  19. #include "switch/EncodingScheme.h"
  20. #include "util/Bits.h"
  21. #include "util/Endian.h"
  22. #include "util/Hex.h"
  23. int EncodingScheme_getFormNum(struct EncodingScheme* scheme, uint64_t routeLabel)
  24. {
  25. if (scheme->count == 1) {
  26. return 0;
  27. }
  28. for (int i = 0; i < scheme->count; i++) {
  29. struct EncodingScheme_Form* form = &scheme->forms[i];
  30. Assert_true(form->prefixLen > 0 && form->prefixLen < 32);
  31. Assert_true(form->bitCount > 0 && form->bitCount < 32);
  32. if (0 == ((form->prefix ^ (uint32_t)routeLabel) << (32 - form->prefixLen))) {
  33. return i;
  34. }
  35. }
  36. return EncodingScheme_getFormNum_INVALID;
  37. }
  38. bool EncodingScheme_is358(struct EncodingScheme* scheme)
  39. {
  40. struct EncodingScheme_Form v358[3] = {
  41. { .bitCount = 3, .prefixLen = 1, .prefix = 1, },
  42. { .bitCount = 5, .prefixLen = 2, .prefix = 1<<1, },
  43. { .bitCount = 8, .prefixLen = 2, .prefix = 0, }
  44. };
  45. if (scheme->count != 3) { return false; }
  46. for (int i = 0; i < 3; i++) {
  47. if (Bits_memcmp(&v358[i], &scheme->forms[i], sizeof(struct EncodingScheme_Form))) {
  48. return false;
  49. }
  50. }
  51. return true;
  52. }
  53. int EncodingScheme_parseDirector(struct EncodingScheme* scheme, uint64_t label)
  54. {
  55. int formNum = EncodingScheme_getFormNum(scheme, label);
  56. if (formNum == EncodingScheme_getFormNum_INVALID) {
  57. return EncodingScheme_parseDirector_INVALID;
  58. }
  59. struct EncodingScheme_Form* currentForm = &scheme->forms[formNum];
  60. int dir = (label >> currentForm->prefixLen) & Bits_maxBits64(currentForm->bitCount);
  61. if (!EncodingScheme_is358(scheme)) {
  62. // use ^1 to flip slots 0 and 1 in variable width schemes
  63. return dir ^ (scheme->count > 1);
  64. } else {
  65. // slot 0 must always be represented as a 1, so in 358, 0 and 1 are swapped.
  66. if (formNum > 0) {
  67. dir += (dir > 0);
  68. } else {
  69. dir += (dir == 0) - (dir == 1);
  70. }
  71. return dir;
  72. }
  73. }
  74. uint64_t EncodingScheme_serializeDirector(struct EncodingScheme* scheme, int dir, int formNum)
  75. {
  76. if (!EncodingScheme_is358(scheme)) {
  77. if (formNum < 0) {
  78. for (formNum = 0; formNum < scheme->count; formNum++) {
  79. if (!(dir >> scheme->forms[formNum].bitCount)) { break; }
  80. }
  81. }
  82. // use ^1 to flip slots 0 and 1 in variable width schemes
  83. dir ^= (scheme->count > 1);
  84. } else {
  85. if (formNum < 0) {
  86. for (formNum = 0; formNum < scheme->count; formNum++) {
  87. if (!((dir - (!!formNum)) >> scheme->forms[formNum].bitCount)) { break; }
  88. }
  89. }
  90. if (formNum) {
  91. // slot 1 is only represented in form 0 so in all other forms, it is skipped.
  92. dir -= (dir > 0);
  93. } else {
  94. // slot 0 must always be represented as a 1, so 0 and 1 are swapped.
  95. dir += (dir == 0) - (dir == 1);
  96. }
  97. }
  98. if (formNum >= scheme->count) { return ~0ull; }
  99. struct EncodingScheme_Form* f = &scheme->forms[formNum];
  100. return (dir << f->prefixLen) | f->prefix;
  101. }
  102. uint64_t EncodingScheme_convertLabel(struct EncodingScheme* scheme,
  103. uint64_t routeLabel,
  104. int convertTo)
  105. {
  106. int formNum = EncodingScheme_getFormNum(scheme, routeLabel);
  107. if (formNum == EncodingScheme_getFormNum_INVALID) {
  108. return EncodingScheme_convertLabel_INVALID;
  109. }
  110. struct EncodingScheme_Form* currentForm = &scheme->forms[formNum];
  111. if (scheme->count == 1
  112. || (routeLabel & Bits_maxBits64(currentForm->prefixLen + currentForm->bitCount)) == 1)
  113. {
  114. // fixed width encoding or it's a self label, this is easy
  115. switch (convertTo) {
  116. case 0:
  117. case EncodingScheme_convertLabel_convertTo_CANNONICAL: return routeLabel;
  118. default: return EncodingScheme_convertLabel_INVALID;
  119. }
  120. }
  121. routeLabel >>= currentForm->prefixLen;
  122. uint64_t director = routeLabel & Bits_maxBits64(currentForm->bitCount);
  123. routeLabel >>= currentForm->bitCount;
  124. // ACKTUNG: Magic afoot!
  125. // Conversions are necessary for two reasons.
  126. // #1 ensure 0001 always references interface 1, the self interface.
  127. // #2 reuse interface the binary encoding for interface 1 in other EncodingForms
  128. // because interface 1 cannot be expressed as anything other than 0001
  129. if (!EncodingScheme_is358(scheme)) {
  130. // don't pull this bug-workaround crap for sane encodings schemes.
  131. } else if ((currentForm->prefix & Bits_maxBits64(currentForm->prefixLen)) == 1) {
  132. // Swap 0 and 1 if the prefix is 1, this makes 0001 alias to 1
  133. // because 0 can never show up in the wild, we reuse it for 1.
  134. director = director - (director == 1) + (director == 0);
  135. } else {
  136. // Reuse the number 1 for 2 and 2 for 3 etc. to gain an extra slot in all other forms.
  137. director += (director > 0);
  138. }
  139. if (convertTo == EncodingScheme_convertLabel_convertTo_CANNONICAL) {
  140. // Take into account the fact that if the destination form does not have a 1 prefix,
  141. // an extra number will be available.
  142. int minBitsA = Bits_log2x64(director) + 1;
  143. int minBitsB = Bits_log2x64(director - (director > 0)) + 1;
  144. for (int i = 0; i < scheme->count; i++) {
  145. struct EncodingScheme_Form* form = &scheme->forms[i];
  146. int minBits = ((form->prefix & Bits_maxBits64(form->prefixLen)) == 1)
  147. ? minBitsA : minBitsB;
  148. if (form->bitCount >= minBits) {
  149. convertTo = i;
  150. break;
  151. }
  152. }
  153. }
  154. if (convertTo < 0 || convertTo >= scheme->count) {
  155. // convertTo value is insane
  156. return EncodingScheme_convertLabel_INVALID;
  157. }
  158. struct EncodingScheme_Form* nextForm = &scheme->forms[convertTo];
  159. if (!EncodingScheme_is358(scheme)) {
  160. // don't pull this bug-workaround crap for sane encodings schemes.
  161. } else if ((nextForm->prefix & Bits_maxBits64(nextForm->prefixLen)) == 1) {
  162. // Swap 1 and 0 back if necessary.
  163. director = director - (director == 1) + (director == 0);
  164. } else {
  165. // Or move the numbers down by one.
  166. director -= (director > 0);
  167. }
  168. if ((Bits_log2x64(director) + 1) > nextForm->bitCount) {
  169. // won't fit in requested form
  170. return EncodingScheme_convertLabel_INVALID;
  171. }
  172. if (Bits_log2x64(routeLabel) + EncodingScheme_formSize(nextForm) > 59) {
  173. return EncodingScheme_convertLabel_INVALID;
  174. }
  175. routeLabel <<= nextForm->bitCount;
  176. routeLabel |= director;
  177. routeLabel <<= nextForm->prefixLen;
  178. routeLabel |= nextForm->prefix;
  179. if ((routeLabel & Bits_maxBits64(nextForm->prefixLen + nextForm->bitCount)) == 1) {
  180. // looks like a self-route
  181. return EncodingScheme_convertLabel_INVALID;
  182. }
  183. return routeLabel;
  184. }
  185. /**
  186. * Decode a form from its binary representation.
  187. * Can only use a maximum of 41 bits.
  188. *
  189. * One or more of these binary representation are bitwise concatenated to
  190. * give an unsigned integer; which is encoded in **little endian** to give
  191. * the serialization of Encoding Scheme.
  192. *
  193. * Ten least significant bits of a form are:
  194. *
  195. * 1
  196. * 0 1 2 3 4 5 6 7 0 1
  197. * +-+-+-+-+-+-+-+-+-+-+
  198. * 0 | bitcount| preflen |
  199. * +-+-+-+-+-+-+-+-+-+-+
  200. *
  201. * Previous 'preflen' bits are the prefix
  202. *
  203. * @param out the output which will be populated with the encoding form data.
  204. * @param data the binary data in host order.
  205. * @return the number of bits of data which were consumed by the decoding.
  206. * If the content is definitely not an encoding form, 0 is returned.
  207. */
  208. static inline int decodeForm(struct EncodingScheme_Form* out, uint64_t d)
  209. {
  210. out->prefixLen = d & Bits_maxBits64(5);
  211. d >>= 5;
  212. int bitCount = d & Bits_maxBits64(5);
  213. if (bitCount < 1) {
  214. return 0;
  215. }
  216. out->bitCount = bitCount;
  217. d >>= 5;
  218. out->prefix = d & Bits_maxBits64(out->prefixLen);
  219. return 5 + 5 + out->prefixLen;
  220. }
  221. static inline int encodeForm(struct EncodingScheme_Form* in, uint64_t* data, int bits)
  222. {
  223. *data |= ((uint64_t)in->prefixLen & Bits_maxBits64(5)) << bits;
  224. bits += 5;
  225. *data |= ((uint64_t)in->bitCount & Bits_maxBits64(5)) << bits;
  226. bits += 5;
  227. *data |= ((uint64_t)in->prefix & Bits_maxBits64(in->prefixLen)) << bits;
  228. return 5 + 5 + in->prefixLen;
  229. }
  230. bool EncodingScheme_isSane(struct EncodingScheme* scheme)
  231. {
  232. // Check for obviously insane encoding.
  233. if (scheme->count == 0) {
  234. // No encoding schemes
  235. return false;
  236. }
  237. if (scheme->count > 31) {
  238. // impossible, each form must have a different bitCount and bitCount
  239. // can only be expressed in 5 bits limiting it to 31 bits max and a form
  240. // using zero bits is not allowed so there are only 31 max possibilities.
  241. return false;
  242. }
  243. if (scheme->count == 1) {
  244. // Fixed width encoding, prefix is not allowed and bitcount must be non-zero
  245. if (scheme->forms[0].prefixLen != 0 || scheme->forms[0].prefix != 0) {
  246. // prefixLen must be 0
  247. return false;
  248. }
  249. if (scheme->forms[0].bitCount == 0 || scheme->forms[0].bitCount > 31) {
  250. // bitcount must be non-zero and can't overflow the number
  251. return false;
  252. }
  253. return true;
  254. }
  255. // Variable width encoding.
  256. for (int i = 0; i < scheme->count; i++) {
  257. struct EncodingScheme_Form* form = &scheme->forms[i];
  258. if (form->prefixLen == 0 || form->prefixLen > 31) {
  259. // Prefix must exist in order to distinguish between forms
  260. return false;
  261. }
  262. if (form->bitCount == 0 || form->bitCount > 31) {
  263. // Bitcount must be non-zero
  264. return false;
  265. }
  266. if (EncodingScheme_formSize(form) > 59) {
  267. // cannot be represented in the usable space in a label
  268. return false;
  269. }
  270. if (i > 0 && form->bitCount <= scheme->forms[i-1].bitCount) {
  271. // Forms must be in ascending order.
  272. return false;
  273. }
  274. for (int j = 0; j < scheme->count; j++) {
  275. // Forms must be distinguishable by their prefixes.
  276. if (j != i
  277. && (scheme->forms[j].prefix & Bits_maxBits64(form->prefixLen)) == form->prefix)
  278. {
  279. return false;
  280. }
  281. }
  282. }
  283. return true;
  284. }
  285. List* EncodingScheme_asList(struct EncodingScheme* list, struct Allocator* alloc)
  286. {
  287. Assert_ifParanoid(EncodingScheme_isSane(list));
  288. List* scheme = List_new(alloc);
  289. for (int i = (int)list->count - 1; i >= 0; i--) {
  290. Dict* form = Dict_new(alloc);
  291. Dict_putIntC(form, "prefixLen", list->forms[i].prefixLen, alloc);
  292. Dict_putIntC(form, "bitCount", list->forms[i].bitCount, alloc);
  293. if (list->forms[i].prefixLen == 0) {
  294. Dict_putStringCC(form, "prefix", "", alloc);
  295. } else {
  296. String* pfx = String_newBinary(NULL, 8, alloc);
  297. uint32_t prefix_be = Endian_hostToBigEndian32(list->forms[i].prefix);
  298. Hex_encode(pfx->bytes, 8, (uint8_t*)&prefix_be, 4);
  299. while (pfx->bytes[0] == '0' && pfx->len > 2) {
  300. pfx->bytes += 2;
  301. pfx->len -= 2;
  302. }
  303. Dict_putStringC(form, "prefix", pfx, alloc);
  304. }
  305. List_addDict(scheme, form, alloc);
  306. }
  307. return scheme;
  308. }
  309. struct EncodingScheme* EncodingScheme_fromList(List* scheme, struct Allocator* alloc)
  310. {
  311. struct EncodingScheme* list = Allocator_malloc(alloc, sizeof(struct EncodingScheme));
  312. list->count = List_size(scheme);
  313. list->forms = Allocator_malloc(alloc, sizeof(struct EncodingScheme_Form) * list->count);
  314. for (int i = 0; i < (int)list->count; i++) {
  315. Dict* form = List_getDict(scheme, i);
  316. uint64_t* prefixLen = Dict_getIntC(form, "prefixLen");
  317. uint64_t* bitCount = Dict_getIntC(form, "bitCount");
  318. String* prefixStr = Dict_getStringC(form, "prefix");
  319. if (!prefixLen || !bitCount || !prefixStr || prefixStr->len != 8) {
  320. return NULL;
  321. }
  322. uint32_t prefix_be;
  323. if (Hex_decode((uint8_t*)&prefix_be, 4, prefixStr->bytes, 8) != 4) {
  324. return NULL;
  325. }
  326. list->forms[i].prefixLen = *prefixLen;
  327. list->forms[i].bitCount = *bitCount;
  328. list->forms[i].prefix = Endian_bigEndianToHost32(prefix_be);
  329. }
  330. if (!EncodingScheme_isSane(list)) {
  331. return NULL;
  332. }
  333. return list;
  334. }
  335. String* EncodingScheme_serialize(struct EncodingScheme* list,
  336. struct Allocator* alloc)
  337. {
  338. Assert_ifParanoid(EncodingScheme_isSane(list));
  339. // Create the string as the largest that is possible for the list size.
  340. String* out = String_newBinary(NULL, list->count * 6, alloc);
  341. int bits = 0;
  342. int outIndex = 0;
  343. uint64_t block = 0;
  344. for (int listIndex = 0; listIndex < (int)list->count; listIndex++) {
  345. bits += encodeForm(&list->forms[listIndex], &block, bits);
  346. while (bits > 8) {
  347. Assert_true(outIndex < (int)out->len);
  348. out->bytes[outIndex++] = (uint8_t) (block & 0xff);
  349. bits -= 8;
  350. block >>= 8;
  351. }
  352. }
  353. if (bits > 0) {
  354. out->bytes[outIndex++] = (uint8_t) (block & 0xff);
  355. }
  356. out->len = outIndex;
  357. return out;
  358. }
  359. struct EncodingScheme* EncodingScheme_deserialize(String* data,
  360. struct Allocator* alloc)
  361. {
  362. struct EncodingScheme_Form* forms = NULL;
  363. int outCount = 0;
  364. uint64_t block = 0;
  365. int bits = 0;
  366. int dataIndex = 0;
  367. for (;;) {
  368. // load data into the block from the incoming data source
  369. while (bits < 56 && dataIndex < (int)data->len) {
  370. block |= (((uint64_t)data->bytes[dataIndex++] & 0xff) << bits);
  371. bits += 8;
  372. }
  373. struct EncodingScheme_Form next;
  374. int ret = decodeForm(&next, block);
  375. bits -= ret;
  376. if (!ret || bits < 0) {
  377. if (block || dataIndex < (int)data->len || bits < 0) {
  378. // Invalid encoding
  379. return NULL;
  380. }
  381. break;
  382. }
  383. block >>= ret;
  384. Assert_true((next.prefix >> next.prefixLen) == 0);
  385. outCount += 1;
  386. forms = Allocator_realloc(alloc, forms, outCount * sizeof(struct EncodingScheme_Form));
  387. Bits_memcpy(&forms[outCount-1], &next, sizeof(struct EncodingScheme_Form));
  388. }
  389. struct EncodingScheme* out = Allocator_clone(alloc, (&(struct EncodingScheme) {
  390. .forms = forms,
  391. .count = outCount
  392. }));
  393. return EncodingScheme_isSane(out) ? out : NULL;
  394. }
  395. struct EncodingScheme* EncodingScheme_defineFixedWidthScheme(int bitCount, struct Allocator* alloc)
  396. {
  397. struct NumberCompress_FixedWidthScheme
  398. {
  399. struct EncodingScheme scheme;
  400. struct EncodingScheme_Form form;
  401. };
  402. struct NumberCompress_FixedWidthScheme* out =
  403. Allocator_malloc(alloc, sizeof(struct NumberCompress_FixedWidthScheme));
  404. struct NumberCompress_FixedWidthScheme scheme = {
  405. .scheme = { .count = 1, .forms = &out->form },
  406. .form = { .bitCount = bitCount, .prefixLen = 0, .prefix = 0, },
  407. };
  408. Bits_memcpy(out, &scheme, sizeof(struct NumberCompress_FixedWidthScheme));
  409. Assert_true(EncodingScheme_isSane(&out->scheme));
  410. return &out->scheme;
  411. }
  412. struct EncodingScheme* EncodingScheme_defineDynWidthScheme(struct EncodingScheme_Form* forms,
  413. int formCount,
  414. struct Allocator* alloc)
  415. {
  416. struct EncodingScheme_Form* formsCopy =
  417. Allocator_malloc(alloc, sizeof(struct EncodingScheme_Form) * formCount);
  418. Bits_memcpy(formsCopy, forms, sizeof(struct EncodingScheme_Form) * formCount);
  419. struct EncodingScheme* scheme = Allocator_clone(alloc, (&(struct EncodingScheme) {
  420. .count = formCount,
  421. .forms = formsCopy
  422. }));
  423. Assert_ifParanoid(EncodingScheme_isSane(scheme));
  424. return scheme;
  425. }
  426. int EncodingScheme_compare(struct EncodingScheme* a, struct EncodingScheme* b)
  427. {
  428. if (a->count == b->count) {
  429. return Bits_memcmp(a->forms, b->forms, sizeof(struct EncodingScheme_Form) * a->count);
  430. }
  431. return a->count > b->count ? 1 : -1;
  432. }
  433. /**
  434. * Return true if the route is to the switch's router interface.
  435. */
  436. int EncodingScheme_isSelfRoute(struct EncodingScheme* scheme, uint64_t routeLabel)
  437. {
  438. int formNum = EncodingScheme_getFormNum(scheme, routeLabel);
  439. if (formNum == EncodingScheme_getFormNum_INVALID) {
  440. return 0;
  441. }
  442. struct EncodingScheme_Form* currentForm = &scheme->forms[formNum];
  443. return (routeLabel & Bits_maxBits64(currentForm->prefixLen + currentForm->bitCount)) == 1;
  444. }
  445. int EncodingScheme_isOneHop(struct EncodingScheme* scheme, uint64_t routeLabel)
  446. {
  447. int fn = EncodingScheme_getFormNum(scheme, routeLabel);
  448. if (fn == EncodingScheme_getFormNum_INVALID) { return 0; }
  449. struct EncodingScheme_Form* form = &scheme->forms[fn];
  450. return (Bits_log2x64(routeLabel) == form->prefixLen + form->bitCount);
  451. }