You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

btrie.c 78KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643
  1. /* Level-Compressed Tree Bitmap (LC-TBM) Trie implementation
  2. *
  3. * Contributed by Geoffrey T. Dairiki <dairiki@dairiki.org>
  4. *
  5. * This file is released under a "Three-clause BSD License".
  6. *
  7. * Copyright (c) 2013, Geoffrey T. Dairiki
  8. * All rights reserved.
  9. *
  10. * Redistribution and use in source and binary forms, with or without
  11. * modification, are permitted provided that the following conditions
  12. * are met:
  13. *
  14. * * Redistributions of source code must retain the above copyright
  15. * notice, this list of conditions and the following disclaimer.
  16. *
  17. * * Redistributions in binary form must reproduce the above
  18. * copyright notice, this list of conditions and the following
  19. * disclaimer in the documentation and/or other materials provided
  20. * with the distribution.
  21. *
  22. * * Neither the name of Geoffrey T. Dairiki nor the names of other
  23. * contributors may be used to endorse or promote products derived
  24. * from this software without specific prior written permission.
  25. *
  26. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  27. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  28. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  29. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GEOFFREY
  30. * T. DAIRIKI BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  31. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  32. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  33. * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  34. * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  35. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
  36. * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  37. * DAMAGE.
  38. */
  39. /*****************************************************************
  40. *
  41. * This code implements a routing table conceptually based on a binary
  42. * trie structure. Internally, the trie is represented by two types
  43. * of compound nodes: "multibit nodes", which contain the top few
  44. * levels of an entire binary subtree; and "level compression" (LC)
  45. * nodes which represent a (potentially long) chain of out-degree one
  46. * (single child) binary nodes (possibly ending at a terminal node).
  47. *
  48. * The multibit nodes are represented using a "Tree Bitmap" structure
  49. * (more on this below), which is very efficient --- both in terms of
  50. * memory usage and lookup speed --- at representing densely branching
  51. * parts of the trie. The LC nodes can efficiently represent long
  52. * non-branching chains of binary trie nodes. Using both node types
  53. * together results in efficient representation of both the sparse and
  54. * dense parts of a binary trie.
  55. *
  56. * Graphically, here's the rough idea:
  57. *
  58. * ........
  59. * .LC o .
  60. * . / . LC nodes can
  61. * . o . <= represent long chains
  62. * . \ . of (non-branching) binary
  63. * . o . trie nodes
  64. * . / .
  65. * . o .
  66. * ......../.....
  67. * .TBM o .
  68. * . / \ . TBM nodes can represent
  69. * . o * . <= several levels of densely
  70. * . / \ . branching binary trie nodes
  71. * . o o .
  72. * ......./.....\.......
  73. * .TBM o .. o LC.
  74. * . / \ .. \ .
  75. * . o o .. o .
  76. * . / / \ .. \ .
  77. * . * o *.. o .
  78. * ...../....... / .
  79. * . o LC. . o .
  80. * . \ . .....\......
  81. * . * . . o TBM.
  82. * ........ . / \ .
  83. * . o o .
  84. * . / \ \ .
  85. * .* * *.
  86. * ...........
  87. *
  88. * Terminology
  89. * -----------
  90. *
  91. * node
  92. * Usually, in the comments below, "node" will be used to refer to
  93. * a compound node: either a multibit (TBM) node or an LC node.
  94. *
  95. * "internal node" or "prefix"
  96. * The terms "prefix" or "internal node" are used to refer to
  97. * a node in the binary trie which is internal to a multibit (TBM)
  98. * node.
  99. *
  100. * ----------------------------------------------------------------
  101. *
  102. * Internal Representation of the Nodes
  103. * ====================================
  104. *
  105. * Multibit (TBM) Nodes
  106. * ~~~~~~~~~~~~~~~~~~~~
  107. *
  108. * The multibit nodes are represented using a "Tree Bitmap" (TBM)
  109. * structure as described by Eatherton, Dittia and Varghese[1]. See
  110. * the paper referenced below for basic details.
  111. *
  112. * A multibit node, represents several levels of a binary trie.
  113. * For example, here is a multibit node of stride 2 (which represent
  114. * two levels of a binary trie.
  115. *
  116. * +------- | ------+
  117. * | multi o |
  118. * | bit / \ |
  119. * | node / \ |
  120. * | o * |
  121. * +--- / \ - / \ --+
  122. * O
  123. *
  124. * Note that, for a multibit node of stride S, there are 2^S - 1 internal
  125. * nodes, each of which may have data (or not) associated with them, and
  126. * 2^S "external paths" leading to other (possibly compound nodes).
  127. * (In the diagram above, one of three internal node (the one denoted by "*")
  128. * has data, and one of four extending paths leads to an external node
  129. * (denoted by the 'O').)
  130. *
  131. * The TBM structure can represent these bitmaps in a very memory-efficient
  132. * manner.
  133. *
  134. * Each TBM node consists of two bitmaps --- the "internal bitmap" and the
  135. * "extending paths bitmap" --- and a pointer which points to an array
  136. * which contains both the extending path ("child") nodes and any
  137. * internal prefix data for the TBM node.
  138. *
  139. * +--------+--------+
  140. * TBM | ext bm | int bm |
  141. * Node +--------+--------+
  142. * | pointer |----+
  143. * +-----------------+ |
  144. * |
  145. * |
  146. * +-----------------+ |
  147. * | extending path | |
  148. * | node[N-1] | |
  149. * +-----------------+ |
  150. * / ... / |
  151. * / ... / |
  152. * +-----------------+ |
  153. * | extending path | |
  154. * | node[0] | |
  155. * +-----------------+<---+
  156. * | int. data[M-1] |
  157. * +-----------------+
  158. * / ... /
  159. * +-----------------+
  160. * | int. data[0] |
  161. * +-----------------+
  162. *
  163. * The extending paths bitmap (or "ext bitmap") has one bit for each
  164. * possible "extending path" from the bottom of the multibit node. To
  165. * check if a particular extending path is present, one checks to see if
  166. * the corresponding bit is set in the ext bitmap. The index into the
  167. * array of children for that path can be found by counting the number
  168. * of set bits to the left of that bit.
  169. *
  170. * Similarly, the internal bitmap has one bit for each binary node
  171. * which is internal to the multibit node. To determine whether there
  172. * is data stored for an internal prefix, one checks the corresponding
  173. * bit in the internal bitmap. As for extending paths, the index into
  174. * the array of internal data is found by counting the number of set
  175. * bits to the left of that bit.
  176. *
  177. * To save space in the node structure, the node data array is stored
  178. * contiguously with the node extending path array. The single
  179. * ("children") pointer in the TBM structure points to the beginning
  180. * of the array of extending path nodes and to (one past) the end of
  181. * the the internal data array.
  182. *
  183. * The multibit stride is chosen so that the entire TBM node structure fits
  184. * in the space of two pointers. On 32 bit machines this means the stride
  185. * is four (each of the two bitmaps is 16 bits); on 32 bit machines the
  186. * stride is five.
  187. *
  188. * Note that there are only 2^stride - 1 internal prefixes in a TBM
  189. * node. That means there is one unused bit in the internal bitmap.
  190. * We require that that bit must always be clear for a TBM node. (If
  191. * set, it indicates that the structure represents, instead, an LC
  192. * node. See below.)
  193. *
  194. * ----------------------------------------------------------------
  195. *
  196. * Level Compression (LC) Nodes
  197. * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  198. *
  199. * LC nodes are used to represent a chain of out-degree-one (single
  200. * child) prefixes in the binary trie. The are represented by a bit
  201. * string (the "relative prefix") along with its length and a pointer
  202. * to the extending path (the next node past the LC node.)
  203. *
  204. *
  205. * Non-Terminal LC Node:
  206. *
  207. * +------------------+-------+
  208. * | relative prefix |1|0|len|
  209. * +------------------+-------+
  210. * | ptr.child |--+
  211. * +--------------------------+ |
  212. * |
  213. * |
  214. * +--------------------------+ |
  215. * | Next node - | |
  216. * | either LC or TBM | |
  217. * | | |
  218. * +--------------------------+<-+
  219. *
  220. * The Relative Prefix
  221. * -------------------
  222. *
  223. * The maximum relative prefix per LC node is selected so that (again)
  224. * the entire node structure fits in the space of two pointers. On 32 bit
  225. * machines, the maximum relative prefix is 24 bits; on 62 bit machines
  226. * the limit is 56 bits.
  227. *
  228. * In the LC node structure, the relative prefix is stored as an array
  229. * of bytes. To avoid some bit-shifting during tree searches, these
  230. * bytes are byte-aligned with the global prefix. In other words, in
  231. * general there are (pos % 8) "pad" bits at the beginning of the
  232. * relative prefix --- where pos "starting bit" (or depth in the
  233. * binary tree) of the LC node --- which really belong to the parent
  234. * node(s) of the LC node. For efficiency (so that we don't have to
  235. * mask them out when matching) we require that these pad bits be
  236. * correct --- they must match the path which leads to the LC node.
  237. *
  238. * The relative prefix length stored in the LC node structure does not
  239. * count the pad bits.
  240. *
  241. * Terminal Node Compression
  242. * -------------------------
  243. *
  244. * For memory efficiency, we also support "terminal LC" nodes. When
  245. * the extension path from an LC node consists a single terminal node,
  246. * we store that terminal nodes data directly in the parent LC node.
  247. *
  248. * Instead of this:
  249. *
  250. * +------------------+-------+
  251. * | relative prefix |1|0|len|
  252. * +------------------+-------+
  253. * | ptr.child |--+
  254. * +--------------------------+ |
  255. * |
  256. * +--------------------------+ |
  257. * | Terminal Node (TBM node, | |
  258. * | empty except for the | |
  259. * +--| root internal node.) | |
  260. * | +--------------------------+<-+
  261. * |
  262. * +->+--------------------------+
  263. * | terminal node data |
  264. * +--------------------------+
  265. *
  266. * We can do this:
  267. *
  268. * +------------------+-------+
  269. * | relative prefix |1|1|len|
  270. * +------------------+-------+
  271. * | terminal node data |
  272. * +--------------------------+
  273. *
  274. * Terminal LC nodes are differentiated from non-terminal LC nodes
  275. * by the setting of the is_terminal flag.
  276. *
  277. * Node Structure Packing Details
  278. * ------------------------------
  279. *
  280. * The LC and TBM node structures are carefully packed so that the
  281. * "is_lc" flag (which indicates that a node is an LC node)
  282. * corresponds to the one unused bit in the internal bitmap of the TBM
  283. * node structure (which we require to be zero for TBM nodes).
  284. *
  285. * ----------------------------------------------------------------
  286. *
  287. * References
  288. * ==========
  289. *
  290. * [1] Will Eatherton, George Varghese, and Zubin Dittia. 2004. Tree
  291. * bitmap: hardware/software IP lookups with incremental
  292. * updates. SIGCOMM Comput. Commun. Rev. 34, 2 (April 2004),
  293. * 97-122. DOI=10.1145/997150.997160
  294. * http://doi.acm.org/10.1145/997150.997160
  295. * http://comnet.kaist.ac.kr/yhlee/CN_2008_Spring/readings/Eath-04-tree_bitmap.pdf
  296. *
  297. ****************************************************************/
  298. #include <stdio.h>
  299. #include <stdlib.h>
  300. #include <string.h>
  301. #include <setjmp.h>
  302. #if defined(TEST) && defined(NDEBUG)
  303. # warning undefining NDEBUG for TEST build
  304. # undef NDEBUG
  305. #endif
  306. #include <assert.h>
  307. #include "btrie.h"
  308. #include "libutil/mem_pool.h"
  309. #ifdef __SIZEOF_POINTER__
  310. #define SIZEOF_VOID_P __SIZEOF_POINTER__
  311. #else
  312. #if defined(__ILP32__) || defined(__ILP32) || defined(_ILP32)
  313. # define SIZEOF_VOID_P 4
  314. #elif defined(__ILP64__) || defined(__ILP64) || defined(_ILP64)
  315. # define SIZEOF_VOID_P 8
  316. #elif defined(__LLP64__) || defined(__LLP64) || defined(_LLP64) || defined(_WIN64)
  317. # define SIZEOF_VOID_P 8
  318. #elif defined(__LP64__) || defined(__LP64) || defined(_LP64)
  319. # define SIZEOF_VOID_P 8
  320. #elif defined(UINTPTR_MAX) && defined(UINT64_MAX) && (UINTPTR_MAX == UINT64_MAX)
  321. # define SIZEOF_VOID_P 8
  322. #else
  323. # define SIZEOF_VOID_P 4
  324. #endif
  325. #endif
  326. #if SIZEOF_VOID_P == 4
  327. # define TBM_STRIDE 4
  328. #elif SIZEOF_VOID_P == 8
  329. # define TBM_STRIDE 5
  330. #else
  331. # error "Unsupported word size"
  332. #endif
  333. #ifndef NO_STDINT_H
  334. # if TBM_STRIDE == 4
  335. typedef uint16_t tbm_bitmap_t;
  336. # else
  337. typedef uint32_t tbm_bitmap_t;
  338. # endif
  339. #else /* NO_STDINT_H */
  340. # if TBM_STRIDE == 4
  341. # if SIZEOF_SHORT == 2
  342. typedef short unsigned tbm_bitmap_t;
  343. # else
  344. # error "can not determine type for 16 bit unsigned int"
  345. # endif
  346. # else /* TBM_STRIDE == 5 */
  347. # if SIZEOF_INT == 4
  348. typedef unsigned tbm_bitmap_t;
  349. # elif SIZEOF_LONG == 4
  350. typedef long unsigned tbm_bitmap_t;
  351. # else
  352. # error "can not determine type for 32 bit unsigned int"
  353. # endif
  354. # endif
  355. #endif
  356. #define TBM_FANOUT (1U << TBM_STRIDE)
  357. #define LC_BYTES_PER_NODE (SIZEOF_VOID_P - 1)
  358. typedef union node_u node_t;
  359. /* The tbm_node and lc_node structs must be packed so that the the
  360. * high bit (LC_FLAGS_IS_LC) of lc_flags in the the lc_node struct
  361. * coincides with bit zero (the most significant bit) of tbm_node's
  362. * int_bm. (This bit is how we differentiate between the two node
  363. * types. It is always clear for a tbm_node and always set for an
  364. * lc_node.)
  365. */
  366. struct tbm_node
  367. {
  368. #ifdef WORDS_BIGENDIAN
  369. tbm_bitmap_t int_bm; /* the internal bitmap */
  370. tbm_bitmap_t ext_bm; /* extending path ("external") bitmap */
  371. #else
  372. tbm_bitmap_t ext_bm; /* extending path ("external") bitmap */
  373. tbm_bitmap_t int_bm; /* the internal bitmap */
  374. #endif
  375. union
  376. {
  377. node_t *children; /* pointer to array of children */
  378. const void **data_end; /* one past end of internal prefix data array */
  379. } ptr;
  380. };
  381. struct lc_node
  382. {
  383. /* lc_flags contains the LC prefix length and a couple of bit flags
  384. * (apparently char-sized bit fields are a gcc extension)
  385. */
  386. # define LC_FLAGS_IS_LC 0x80
  387. # define LC_FLAGS_IS_TERMINAL 0x40
  388. # define LC_FLAGS_LEN_MASK 0x3f
  389. #ifdef WORDS_BIGENDIAN
  390. btrie_oct_t lc_flags;
  391. btrie_oct_t prefix[LC_BYTES_PER_NODE];
  392. #else
  393. btrie_oct_t prefix[LC_BYTES_PER_NODE];
  394. btrie_oct_t lc_flags;
  395. #endif
  396. union
  397. {
  398. node_t *child; /* pointer to child (if !is_terminal) */
  399. const void *data; /* the prefix data (if is_terminal) */
  400. } ptr;
  401. };
  402. union node_u
  403. {
  404. struct tbm_node tbm_node;
  405. struct lc_node lc_node;
  406. };
  407. struct free_hunk
  408. {
  409. struct free_hunk *next;
  410. };
  411. #define MAX_CHILD_ARRAY_LEN (TBM_FANOUT + TBM_FANOUT / 2)
  412. struct btrie
  413. {
  414. node_t root;
  415. rspamd_mempool_t *mp;
  416. struct free_hunk *free_list[MAX_CHILD_ARRAY_LEN];
  417. jmp_buf exception;
  418. /* mem mgmt stats */
  419. size_t alloc_total; /* total bytes allocated from mempool */
  420. size_t alloc_data; /* bytes allocated for TBM node int. prefix data */
  421. size_t alloc_waste; /* bytes wasted by rounding of data array size */
  422. #ifdef BTRIE_DEBUG_ALLOC
  423. size_t alloc_hist[MAX_CHILD_ARRAY_LEN * 2]; /* histogram of alloc sizes */
  424. #endif
  425. /* trie stats */
  426. size_t n_entries; /* number of entries */
  427. size_t n_tbm_nodes; /* total number of TBM nodes in tree */
  428. size_t n_lc_nodes; /* total number of LC nodes in tree */
  429. };
  430. /****************************************************************
  431. *
  432. * Memory management
  433. *
  434. * We will need to frequently resize child/data arrays. The current
  435. * mempool implementation does not support resizing/freeing, so here
  436. * we roll our own.
  437. */
  438. static inline void _free_hunk(struct btrie *btrie, void *buf, unsigned n_nodes)
  439. {
  440. struct free_hunk *hunk = buf;
  441. hunk->next = btrie->free_list[n_nodes - 1];
  442. btrie->free_list[n_nodes - 1] = hunk;
  443. }
  444. static inline void *
  445. _get_hunk(struct btrie *btrie, unsigned n_nodes)
  446. {
  447. struct free_hunk *hunk = btrie->free_list[n_nodes - 1];
  448. if (hunk != NULL)
  449. btrie->free_list[n_nodes - 1] = hunk->next;
  450. return hunk;
  451. }
  452. /* Get pointer to uninitialized child/data array.
  453. *
  454. * Allocates memory for an array of NDATA (void *)s followed by an
  455. * array of NCHILDREN (node_t)s. The returned pointer points to to
  456. * beginning of the children array (i.e. it points to (one past) the
  457. * end of the data array.)
  458. */
  459. static node_t *
  460. alloc_nodes(struct btrie *btrie, unsigned nchildren, unsigned ndata)
  461. {
  462. size_t n_nodes = nchildren + (ndata + 1) / 2;
  463. node_t *hunk;
  464. assert(n_nodes > 0 && n_nodes <= MAX_CHILD_ARRAY_LEN);
  465. hunk = _get_hunk (btrie, n_nodes);
  466. if (hunk == NULL) {
  467. /* Do not have free hunk of exactly the requested size, look for a
  468. * larger hunk. (The funny order in which we scan the buckets is
  469. * heuristically selected in an attempt to minimize unnecessary
  470. * creation of small fragments)
  471. */
  472. size_t n, skip = n_nodes > 4 ? 4 : n_nodes;
  473. for (n = n_nodes + skip; n <= MAX_CHILD_ARRAY_LEN; n++) {
  474. if ((hunk = _get_hunk (btrie, n)) != NULL) {
  475. _free_hunk (btrie, hunk + n_nodes, n - n_nodes);
  476. goto DONE;
  477. }
  478. }
  479. for (n = n_nodes + 1; n < n_nodes + skip && n <= MAX_CHILD_ARRAY_LEN;
  480. n++) {
  481. if ((hunk = _get_hunk (btrie, n)) != NULL) {
  482. _free_hunk (btrie, hunk + n_nodes, n - n_nodes);
  483. goto DONE;
  484. }
  485. }
  486. /* failed to find free hunk, allocate a fresh one */
  487. hunk = rspamd_mempool_alloc0 (btrie->mp, n_nodes * sizeof(node_t));
  488. if (hunk == NULL)
  489. longjmp (btrie->exception, BTRIE_ALLOC_FAILED);
  490. btrie->alloc_total += n_nodes * sizeof(node_t);
  491. }
  492. DONE: btrie->alloc_data += ndata * sizeof(void *);
  493. btrie->alloc_waste += (ndata % 2) * sizeof(void *);
  494. #ifdef BTRIE_DEBUG_ALLOC
  495. btrie->alloc_hist[2 * nchildren + ndata]++;
  496. #endif
  497. /* adjust pointer to allow room for data array before child array */
  498. return hunk + (ndata + 1) / 2;
  499. }
  500. /* Free memory allocated by alloc_nodes */
  501. static void free_nodes(struct btrie *btrie, node_t *buf, unsigned nchildren,
  502. unsigned ndata)
  503. {
  504. size_t n_nodes = nchildren + (ndata + 1) / 2;
  505. assert(n_nodes > 0 && n_nodes <= MAX_CHILD_ARRAY_LEN);
  506. _free_hunk (btrie, buf - (ndata + 1) / 2, n_nodes);
  507. btrie->alloc_data -= ndata * sizeof(void *);
  508. btrie->alloc_waste -= (ndata % 2) * sizeof(void *);
  509. #ifdef BTRIE_DEBUG_ALLOC
  510. btrie->alloc_hist[2 * nchildren + ndata]--;
  511. #endif
  512. }
  513. /* Debugging/development only: */
  514. #ifdef BTRIE_DEBUG_ALLOC
  515. static void
  516. dump_alloc_hist(const struct btrie *btrie)
  517. {
  518. unsigned bin;
  519. size_t total_alloc = 0;
  520. size_t total_free = 0;
  521. size_t total_bytes = 0;
  522. size_t total_waste = 0;
  523. size_t total_free_bytes = 0;
  524. puts("hunk alloc free alloc wasted free");
  525. puts("size hunks hunks bytes bytes bytes");
  526. puts("==== ====== ====== ======== ======== ========");
  527. for (bin = 1; bin < 2 * MAX_CHILD_ARRAY_LEN; bin++) {
  528. size_t n_alloc = btrie->alloc_hist[bin];
  529. size_t bytes = n_alloc * bin * sizeof(void *);
  530. size_t waste_bytes = (bin % 2) * n_alloc * sizeof(void *);
  531. size_t n_free = 0, free_bytes;
  532. if (bin % 2 == 0) {
  533. const struct free_hunk *hunk;
  534. for (hunk = btrie->free_list[bin / 2 - 1]; hunk; hunk = hunk->next)
  535. n_free++;
  536. }
  537. free_bytes = n_free * bin * sizeof(void *);
  538. printf("%3zu: %6zu %6zu %8zu %8zu %8zu\n", bin * sizeof(void *),
  539. n_alloc, n_free, bytes, waste_bytes, free_bytes);
  540. total_alloc += n_alloc;
  541. total_free += n_free;
  542. total_bytes += bytes;
  543. total_waste += waste_bytes;
  544. total_free_bytes += free_bytes;
  545. }
  546. puts("---- ------ ------ -------- -------- --------");
  547. printf("SUM: %6zu %6zu %8zu %8zu %8zu\n",
  548. total_alloc, total_free, total_bytes, total_waste, total_free_bytes);
  549. }
  550. #endif
  551. /****************************************************************
  552. *
  553. * Bit twiddling
  554. *
  555. */
  556. static inline tbm_bitmap_t bit(unsigned b)
  557. {
  558. return 1U << ((1 << TBM_STRIDE) - 1 - b);
  559. }
  560. /* count the number of set bits in bitmap
  561. *
  562. * algorithm from
  563. * http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel
  564. */
  565. static inline unsigned count_bits(tbm_bitmap_t v)
  566. {
  567. /* Count set bits in parallel. */
  568. /* v = (v & 0x5555...) + ((v >> 1) & 0x5555...); */
  569. v -= (v >> 1) & (tbm_bitmap_t) ~0UL / 3;
  570. /* v = (v & 0x3333...) + ((v >> 2) & 0x3333...); */
  571. v = (v & (tbm_bitmap_t) ~0UL / 5) + ((v >> 2) & (tbm_bitmap_t) ~0UL / 5);
  572. /* v = (v & 0x0f0f...) + ((v >> 4) & 0x0f0f...); */
  573. v = (v + (v >> 4)) & (tbm_bitmap_t) ~0UL / 17;
  574. /* v = v % 255; */
  575. #if TBM_STRIDE == 4
  576. /* tbm_bitmap_t is uint16_t, avoid the multiply */
  577. return (v + (v >> 8)) & 0x0ff;
  578. #else
  579. return (v * (tbm_bitmap_t) (~0UL / 255)) >> ((sizeof(tbm_bitmap_t) - 1) * 8);
  580. #endif
  581. }
  582. static inline unsigned count_bits_before(tbm_bitmap_t bm, int b)
  583. {
  584. return b ? count_bits (bm >> ((1 << TBM_STRIDE) - b)) : 0;
  585. }
  586. static inline unsigned count_bits_from(tbm_bitmap_t bm, int b)
  587. {
  588. return count_bits (bm << b);
  589. }
  590. /* extracts a few bits from bitstring, returning them as an integer */
  591. static inline btrie_oct_t extract_bits(const btrie_oct_t *prefix, unsigned pos,
  592. unsigned nbits)
  593. {
  594. if (nbits == 0)
  595. return 0;
  596. else {
  597. unsigned v = (prefix[pos / 8] << 8) + prefix[pos / 8 + 1];
  598. return (v >> (16 - nbits - pos % 8)) & ((1U << nbits) - 1);
  599. }
  600. }
  601. static inline unsigned extract_bit(const btrie_oct_t *prefix, int pos)
  602. {
  603. return (prefix[pos / 8] >> (7 - pos % 8)) & 0x01;
  604. }
  605. /* get mask for high n bits of a byte */
  606. static inline btrie_oct_t high_bits(unsigned n)
  607. {
  608. return (btrie_oct_t) -(1U << (8 - n));
  609. }
  610. /* determine whether two prefixes are equal */
  611. static inline int prefixes_equal(const btrie_oct_t *pfx1,
  612. const btrie_oct_t *pfx2, unsigned len)
  613. {
  614. return (memcmp (pfx1, pfx2, len / 8) == 0
  615. && ((pfx1[len / 8] ^ pfx2[len / 8]) & high_bits (len % 8)) == 0);
  616. }
  617. /* determine length of longest common subprefix */
  618. static inline unsigned common_prefix(const btrie_oct_t *pfx1,
  619. const btrie_oct_t *pfx2, unsigned len)
  620. {
  621. /* algorithm adapted from
  622. * http://graphics.stanford.edu/~seander/bithacks.html#IntegerLogLookup
  623. */
  624. static btrie_oct_t leading_zeros[] =
  625. { 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3,
  626. 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  627. 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1,
  628. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  629. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  630. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  631. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  632. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  633. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  634. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  635. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  636. 0, };
  637. unsigned nb;
  638. for (nb = 0; nb < len / 8; nb++) {
  639. unsigned diff = *pfx1++ ^ *pfx2++;
  640. if (diff != 0)
  641. return 8 * nb + leading_zeros[diff];
  642. }
  643. if (len % 8) {
  644. unsigned n = leading_zeros[*pfx1 ^ *pfx2];
  645. if (n < len % 8)
  646. return 8 * nb + n;
  647. }
  648. return len;
  649. }
  650. /****************************************************************
  651. */
  652. static inline int is_empty_node(const node_t *node)
  653. {
  654. return node->tbm_node.ext_bm == 0 && node->tbm_node.int_bm == 0;
  655. }
  656. static inline int is_lc_node(const node_t *node)
  657. {
  658. return (node->lc_node.lc_flags & LC_FLAGS_IS_LC) != 0;
  659. }
  660. static inline int is_tbm_node(const node_t *node)
  661. {
  662. return !is_lc_node (node);
  663. }
  664. /* is node a TBM node with internal data? */
  665. static inline int has_data(const node_t *node)
  666. {
  667. return is_tbm_node (node) && node->tbm_node.int_bm != 0;
  668. }
  669. static inline unsigned base_index(unsigned pfx, unsigned plen)
  670. {
  671. assert(plen < TBM_STRIDE);
  672. assert(pfx < (1U << plen));
  673. return pfx | (1U << plen);
  674. }
  675. /* initialize node to an empty TBM node */
  676. static inline void init_empty_node(struct btrie *btrie, node_t *node)
  677. {
  678. memset(node, 0, sizeof(*node));
  679. btrie->n_tbm_nodes++;
  680. }
  681. /* get pointer to TBM internal prefix data */
  682. static inline const void **
  683. tbm_data_p(const struct tbm_node *node, unsigned pfx, unsigned plen)
  684. {
  685. unsigned bi = base_index (pfx, plen);
  686. if ((node->int_bm & bit (bi)) == 0)
  687. return NULL; /* no data */
  688. else {
  689. return &node->ptr.data_end[-(int) count_bits_from (node->int_bm, bi)];
  690. }
  691. }
  692. /* add an element to the internal data array */
  693. static void tbm_insert_data(struct btrie *btrie, struct tbm_node *node,
  694. unsigned pfx, unsigned plen, const void *data)
  695. {
  696. /* XXX: don't realloc if already big enough? */
  697. unsigned bi = base_index (pfx, plen);
  698. unsigned nchildren = count_bits (node->ext_bm);
  699. int ndata = count_bits (node->int_bm);
  700. unsigned di = count_bits_before (node->int_bm, bi);
  701. node_t *old_children = node->ptr.children;
  702. const void **old_data_beg = node->ptr.data_end - ndata;
  703. const void **data_beg;
  704. assert((node->int_bm & bit (bi)) == 0);
  705. node->ptr.children = alloc_nodes (btrie, nchildren, ndata + 1);
  706. data_beg = node->ptr.data_end - (ndata + 1);
  707. data_beg[di] = data;
  708. node->int_bm |= bit (bi);
  709. if (nchildren != 0 || ndata != 0) {
  710. memcpy(data_beg, old_data_beg, di * sizeof(data_beg[0]));
  711. memcpy(&data_beg[di + 1], &old_data_beg[di],
  712. (ndata - di) * sizeof(data_beg[0])
  713. + nchildren * sizeof(node_t));
  714. free_nodes (btrie, old_children, nchildren, ndata);
  715. }
  716. }
  717. /* determine whether TBM has internal prefix data for pfx/plen or ancestors */
  718. static inline int has_internal_data(const struct tbm_node *node, unsigned pfx,
  719. unsigned plen)
  720. {
  721. # define BIT(n) (1U << ((1 << TBM_STRIDE) - 1 - (n)))
  722. # define B0() BIT(1) /* the bit for 0/0 */
  723. # define B1(n) (BIT((n) + 2) | B0()) /* the bits for n/1 and its ancestors */
  724. # define B2(n) (BIT((n) + 4) | B1(n >> 1)) /* the bits for n/2 and ancestors */
  725. # define B3(n) (BIT((n) + 8) | B2(n >> 1)) /* the bits for n/3 and ancestors */
  726. # define B4(n) (BIT((n) + 16) | B3(n >> 1)) /* the bits for n/4 and ancestors */
  727. static tbm_bitmap_t ancestors[] =
  728. { 0, B0(), B1(0), B1(1), B2(0), B2(1), B2(2), B2(3), B3(0), B3(1), B3(2),
  729. B3(3), B3(4), B3(5), B3(6), B3(7),
  730. # if TBM_STRIDE == 5
  731. B4(0), B4(1), B4(2), B4(3), B4(4), B4(5), B4(6), B4(7), B4(8), B4(
  732. 9), B4(10), B4(11), B4(12), B4(13), B4(14), B4(15),
  733. # elif TBM_STRIDE != 4
  734. # error "unsupported TBM_STRIDE"
  735. # endif
  736. };
  737. # undef B4
  738. # undef B3
  739. # undef B2
  740. # undef B1
  741. # undef B0
  742. # undef BIT
  743. return (node->int_bm & ancestors[base_index (pfx, plen)]) != 0;
  744. }
  745. /* get pointer to TBM extending path */
  746. static inline node_t *
  747. tbm_ext_path(const struct tbm_node *node, unsigned pfx)
  748. {
  749. if ((node->ext_bm & bit (pfx)) == 0)
  750. return NULL;
  751. else
  752. return &node->ptr.children[count_bits_before (node->ext_bm, pfx)];
  753. }
  754. /* resize TBM node child array to make space for new child node */
  755. static node_t *
  756. tbm_insert_ext_path(struct btrie *btrie, struct tbm_node *node, unsigned pfx)
  757. {
  758. unsigned nchildren = count_bits (node->ext_bm);
  759. unsigned ci = count_bits_before (node->ext_bm, pfx);
  760. int ndata = count_bits (node->int_bm);
  761. node_t *old_children = node->ptr.children;
  762. const void **old_data_beg = node->ptr.data_end - ndata;
  763. assert((node->ext_bm & bit (pfx)) == 0);
  764. node->ptr.children = alloc_nodes (btrie, nchildren + 1, ndata);
  765. init_empty_node (btrie, &node->ptr.children[ci]);
  766. node->ext_bm |= bit (pfx);
  767. if (nchildren != 0 || ndata != 0) {
  768. const void **data_beg = node->ptr.data_end - ndata;
  769. memcpy(data_beg, old_data_beg,
  770. ndata * sizeof(data_beg[0]) + ci * sizeof(node_t));
  771. memcpy(&node->ptr.children[ci + 1], &old_children[ci],
  772. (nchildren - ci) * sizeof(old_children[0]));
  773. free_nodes (btrie, old_children, nchildren, ndata);
  774. }
  775. return &node->ptr.children[ci];
  776. }
  777. static inline int lc_is_terminal(const struct lc_node *node)
  778. {
  779. return (node->lc_flags & LC_FLAGS_IS_TERMINAL) != 0;
  780. }
  781. static inline unsigned lc_len(const struct lc_node *node)
  782. {
  783. return node->lc_flags & LC_FLAGS_LEN_MASK;
  784. }
  785. static inline void lc_init_flags(struct lc_node *node, int is_terminal,
  786. unsigned len)
  787. {
  788. assert((len & ~LC_FLAGS_LEN_MASK) == 0);
  789. node->lc_flags = LC_FLAGS_IS_LC | len;
  790. if (is_terminal)
  791. node->lc_flags |= LC_FLAGS_IS_TERMINAL;
  792. }
  793. static inline void lc_add_to_len(struct lc_node *node, int increment)
  794. {
  795. unsigned new_len = lc_len (node) + increment;
  796. assert((new_len & ~LC_FLAGS_LEN_MASK) == 0);
  797. node->lc_flags = (node->lc_flags & ~LC_FLAGS_LEN_MASK) | new_len;
  798. }
  799. static inline unsigned lc_shift(unsigned pos)
  800. {
  801. return pos / 8;
  802. }
  803. static inline unsigned lc_base(unsigned pos)
  804. {
  805. return 8 * lc_shift (pos);
  806. }
  807. static inline unsigned lc_bits(const struct lc_node *node, unsigned pos)
  808. {
  809. return pos % 8 + lc_len (node);
  810. }
  811. static inline unsigned lc_bytes(const struct lc_node *node, unsigned pos)
  812. {
  813. return (lc_bits (node, pos) + 7) / 8;
  814. }
  815. static inline unsigned lc_leading_bits(const struct lc_node *node, unsigned pos,
  816. unsigned nbits)
  817. {
  818. return extract_bits (node->prefix, pos % 8, nbits);
  819. }
  820. /* Initialize a new terminal LC node
  821. *
  822. * If prefix is too long to fit in a single LC node, then a chain
  823. * of LC nodes will be created.
  824. */
  825. static void init_terminal_node(struct btrie *btrie, node_t *dst, unsigned pos,
  826. const btrie_oct_t *prefix, unsigned len, const void *data)
  827. {
  828. struct lc_node *node = &dst->lc_node;
  829. unsigned nbytes = (len + 7) / 8;
  830. while (nbytes - lc_shift (pos) > LC_BYTES_PER_NODE) {
  831. memcpy(node->prefix, prefix + lc_shift (pos), LC_BYTES_PER_NODE);
  832. lc_init_flags (node, 0, 8 * LC_BYTES_PER_NODE - pos % 8);
  833. node->ptr.child = alloc_nodes (btrie, 1, 0);
  834. pos += lc_len (node);
  835. node = &node->ptr.child->lc_node;
  836. btrie->n_lc_nodes++;
  837. }
  838. memcpy(node->prefix, prefix + lc_shift (pos), nbytes - lc_shift (pos));
  839. lc_init_flags (node, 1, len - pos);
  840. node->ptr.data = data;
  841. btrie->n_lc_nodes++;
  842. }
  843. /* merge chains of multiple LC nodes into a single LC node, if possible.
  844. *
  845. * also ensure that the leading nodes in the LC chain have maximum length.
  846. */
  847. static void coalesce_lc_node(struct btrie *btrie, struct lc_node *node,
  848. unsigned pos)
  849. {
  850. while (!lc_is_terminal (node) && lc_bits (node, pos) < 8 * LC_BYTES_PER_NODE
  851. && is_lc_node (node->ptr.child)) {
  852. struct lc_node *child = &node->ptr.child->lc_node;
  853. unsigned spare_bits = 8 * LC_BYTES_PER_NODE - lc_bits (node, pos);
  854. unsigned end = pos + lc_len (node);
  855. unsigned shift = lc_shift (end) - lc_shift (pos);
  856. if (lc_len (child) <= spare_bits) {
  857. /* node plus child will fit in single node - merge */
  858. memcpy(node->prefix + shift, child->prefix, lc_bytes (child, end));
  859. lc_init_flags (node, lc_is_terminal (child),
  860. lc_len (node) + lc_len (child));
  861. node->ptr = child->ptr;
  862. free_nodes (btrie, (node_t *) child, 1, 0);
  863. btrie->n_lc_nodes--;
  864. }
  865. else {
  866. /* can't merge, but can take some of children bits */
  867. unsigned cshift = lc_shift (end + spare_bits) - lc_shift (end);
  868. memcpy(node->prefix + shift, child->prefix,
  869. LC_BYTES_PER_NODE - shift);
  870. lc_add_to_len (node, spare_bits);
  871. if (cshift)
  872. memmove(child->prefix, child->prefix + cshift,
  873. lc_bytes (child, end) - cshift);
  874. assert(lc_len (child) > spare_bits);
  875. lc_add_to_len (child, -spare_bits);
  876. pos += lc_len (node);
  877. node = child;
  878. }
  879. }
  880. }
  881. static void init_tbm_node(struct btrie *btrie, node_t *node, unsigned pos,
  882. const btrie_oct_t pbyte, const void **root_data_p, node_t *left,
  883. node_t *right);
  884. /* given an LC node at orig_pos, create a new (shorter) node at pos */
  885. static void shorten_lc_node(struct btrie *btrie, node_t *dst, unsigned pos,
  886. struct lc_node *src, unsigned orig_pos)
  887. {
  888. assert(orig_pos < pos);
  889. assert(lc_len (src) >= pos - orig_pos);
  890. assert(dst != (node_t * )src);
  891. if (lc_len (src) == pos - orig_pos && !lc_is_terminal (src)) {
  892. /* just steal the child */
  893. node_t *child = src->ptr.child;
  894. *dst = *child;
  895. free_nodes (btrie, child, 1, 0);
  896. btrie->n_lc_nodes--;
  897. }
  898. else {
  899. struct lc_node *node = &dst->lc_node;
  900. unsigned shift = lc_shift (pos) - lc_shift (orig_pos);
  901. if (shift) {
  902. memmove(node->prefix, src->prefix + shift,
  903. lc_bytes (src, orig_pos) - shift);
  904. node->lc_flags = src->lc_flags;
  905. node->ptr = src->ptr;
  906. }
  907. else {
  908. *node = *src;
  909. }
  910. lc_add_to_len (node, -(pos - orig_pos));
  911. coalesce_lc_node (btrie, node, pos);
  912. }
  913. }
  914. /* convert LC node to non-terminal LC node of length len *in place*
  915. *
  916. * on entry, node must have length at least len
  917. */
  918. static void split_lc_node(struct btrie *btrie, struct lc_node *node,
  919. unsigned pos, unsigned len)
  920. {
  921. node_t *child = alloc_nodes (btrie, 1, 0);
  922. assert(lc_len (node) >= len);
  923. shorten_lc_node (btrie, child, pos + len, node, pos);
  924. lc_init_flags (node, 0, len);
  925. node->ptr.child = child;
  926. btrie->n_lc_nodes++;
  927. }
  928. /* convert non-terminal LC node of length one to a TBM node *in place* */
  929. static void convert_lc_node_1(struct btrie *btrie, struct lc_node *node,
  930. unsigned pos)
  931. {
  932. btrie_oct_t pbyte = node->prefix[0];
  933. node_t *child = node->ptr.child;
  934. node_t *left, *right;
  935. assert(lc_len (node) == 1);
  936. assert(!lc_is_terminal (node));
  937. if (extract_bit (node->prefix, pos % 8))
  938. left = NULL, right = child;
  939. else
  940. left = child, right = NULL;
  941. init_tbm_node (btrie, (node_t *) node, pos, pbyte, NULL, left, right);
  942. free_nodes (btrie, child, 1, 0);
  943. btrie->n_lc_nodes--;
  944. }
  945. /* convert an LC node to TBM node *in place* */
  946. static void convert_lc_node(struct btrie *btrie, struct lc_node *node,
  947. unsigned pos)
  948. {
  949. unsigned len = lc_len (node);
  950. if (len >= TBM_STRIDE) {
  951. unsigned pfx = lc_leading_bits (node, pos, TBM_STRIDE);
  952. struct tbm_node *result = (struct tbm_node *) node;
  953. /* split to LC of len TBM_STRIDE followed by child (extending path) */
  954. split_lc_node (btrie, node, pos, TBM_STRIDE);
  955. /* then convert leading LC node to TBM node */
  956. result->int_bm = 0;
  957. result->ext_bm = bit (pfx);
  958. btrie->n_lc_nodes--;
  959. btrie->n_tbm_nodes++;
  960. }
  961. else if (lc_is_terminal (node)) {
  962. /* convert short terminal LC to TBM (with internal data) */
  963. unsigned pfx = lc_leading_bits (node, pos, len);
  964. const void *data = node->ptr.data;
  965. node_t *result = (node_t *) node;
  966. init_empty_node (btrie, result);
  967. tbm_insert_data (btrie, &result->tbm_node, pfx, len, data);
  968. btrie->n_lc_nodes--;
  969. }
  970. else {
  971. assert(len > 0);
  972. for (; len > 1; len--) {
  973. split_lc_node (btrie, node, pos, len - 1);
  974. convert_lc_node_1 (btrie, &node->ptr.child->lc_node, pos + len - 1);
  975. }
  976. convert_lc_node_1 (btrie, node, pos);
  977. }
  978. }
  979. static void insert_lc_node(struct btrie *btrie, node_t *dst, unsigned pos,
  980. btrie_oct_t pbyte, unsigned last_bit, node_t *tail)
  981. {
  982. struct lc_node *node = &dst->lc_node;
  983. btrie_oct_t mask = 1 << (7 - (pos % 8));
  984. btrie_oct_t bit = last_bit ? mask : 0;
  985. if (mask != 0x01 && is_lc_node (tail)) {
  986. /* optimization: LC tail has room for the extra bit (without shifting) */
  987. assert((tail->lc_node.prefix[0] & mask) == bit);
  988. *node = tail->lc_node;
  989. lc_add_to_len (node, 1);
  990. return;
  991. }
  992. /* add new leading LC node of len 1 */
  993. node->prefix[0] = pbyte | bit;
  994. lc_init_flags (node, 0, 1);
  995. node->ptr.child = alloc_nodes (btrie, 1, 0);
  996. node->ptr.child[0] = *tail;
  997. btrie->n_lc_nodes++;
  998. if (is_lc_node (tail))
  999. coalesce_lc_node (btrie, node, pos);
  1000. }
  1001. /* given:
  1002. * pbyte: the bits in the prefix between lc_base(pos) and pos
  1003. * pfx: the next TBM_STRIDE bits in the prefix starting at pos
  1004. * returns:
  1005. * the bits in the prefix between lc_base(pos + plen) and pos + plen
  1006. */
  1007. static inline btrie_oct_t next_pbyte(btrie_oct_t pbyte, unsigned pos,
  1008. unsigned pfx)
  1009. {
  1010. unsigned end = pos + TBM_STRIDE;
  1011. if (end % 8 != 0) {
  1012. btrie_oct_t nbyte = (btrie_oct_t) pfx << (8 - end % 8);
  1013. if (end % 8 > TBM_STRIDE)
  1014. nbyte |= pbyte & high_bits (pos % 8);
  1015. return nbyte;
  1016. }
  1017. return 0;
  1018. }
  1019. /* construct a new TBM node, given the data and children of the
  1020. * root prefix of the new node.
  1021. */
  1022. static void init_tbm_node(struct btrie *btrie, node_t *dst, unsigned pos,
  1023. const btrie_oct_t pbyte, const void **root_data_p, node_t *left,
  1024. node_t *right)
  1025. {
  1026. struct tbm_node *node = &dst->tbm_node;
  1027. unsigned nchildren = 0;
  1028. unsigned ndata = 0;
  1029. node_t children[TBM_FANOUT];
  1030. const void *data[TBM_FANOUT - 1];
  1031. tbm_bitmap_t ext_bm = 0;
  1032. tbm_bitmap_t int_bm = 0;
  1033. unsigned i, d, pfx_base;
  1034. if (left && is_lc_node (left) && lc_len (&left->lc_node) < TBM_STRIDE)
  1035. convert_lc_node (btrie, &left->lc_node, pos + 1);
  1036. if (right && is_lc_node (right) && lc_len (&right->lc_node) < TBM_STRIDE)
  1037. convert_lc_node (btrie, &right->lc_node, pos + 1);
  1038. /* set internal data for root prefix */
  1039. if (root_data_p) {
  1040. data[ndata++] = *root_data_p;
  1041. int_bm |= bit (base_index (0, 0));
  1042. }
  1043. /* copy internal data from children */
  1044. for (d = 0; d < TBM_STRIDE - 1; d++) {
  1045. if (left && has_data (left)) {
  1046. for (i = 0; i < 1U << d; i++) {
  1047. const void **data_p = tbm_data_p (&left->tbm_node, i, d);
  1048. if (data_p) {
  1049. data[ndata++] = *data_p;
  1050. int_bm |= bit (base_index (i, d + 1));
  1051. }
  1052. }
  1053. }
  1054. if (right && has_data (right)) {
  1055. for (i = 0; i < 1U << d; i++) {
  1056. const void **data_p = tbm_data_p (&right->tbm_node, i, d);
  1057. if (data_p) {
  1058. data[ndata++] = *data_p;
  1059. int_bm |= bit (base_index (i + (1 << d), d + 1));
  1060. }
  1061. }
  1062. }
  1063. }
  1064. /* copy extending paths */
  1065. for (pfx_base = 0; pfx_base < TBM_FANOUT; pfx_base += TBM_FANOUT / 2) {
  1066. node_t *child = pfx_base ? right : left;
  1067. if (child == NULL) {
  1068. continue;
  1069. }
  1070. else if (is_lc_node (child)) {
  1071. unsigned pfx = pfx_base + lc_leading_bits (&child->lc_node, pos + 1,
  1072. TBM_STRIDE - 1);
  1073. /* child is LC node, just shorten it by TBM_STRIDE - 1 */
  1074. shorten_lc_node (btrie, &children[nchildren++], pos + TBM_STRIDE,
  1075. &child->lc_node, pos + 1);
  1076. ext_bm |= bit (pfx);
  1077. }
  1078. else if (!is_empty_node (child)) {
  1079. /* convert deepest internal prefixes of child to extending paths
  1080. * of the new node
  1081. */
  1082. for (i = 0; i < TBM_FANOUT / 2; i++) {
  1083. const void **data_p = tbm_data_p (&child->tbm_node, i,
  1084. TBM_STRIDE - 1);
  1085. node_t *left_ext = tbm_ext_path (&child->tbm_node, 2 * i);
  1086. node_t *right_ext = tbm_ext_path (&child->tbm_node, 2 * i + 1);
  1087. if (data_p || left_ext || right_ext) {
  1088. node_t *ext_path = &children[nchildren++];
  1089. unsigned pfx = pfx_base + i;
  1090. btrie_oct_t npbyte = next_pbyte (pbyte, pos, pfx);
  1091. ext_bm |= bit (pfx);
  1092. if (left_ext == NULL && right_ext == NULL) {
  1093. /* only have data - set ext_path to zero-length terminal LC node */
  1094. lc_init_flags (&ext_path->lc_node, 1, 0);
  1095. ext_path->lc_node.prefix[0] = npbyte;
  1096. ext_path->lc_node.ptr.data = *data_p;
  1097. btrie->n_lc_nodes++;
  1098. }
  1099. else if (data_p || (left_ext && right_ext)) {
  1100. /* have at least two of data, left_ext, right_ext
  1101. * ext_path must be a full TBM node */
  1102. init_tbm_node (btrie, ext_path, pos + TBM_STRIDE,
  1103. npbyte, data_p, left_ext, right_ext);
  1104. }
  1105. else if (left_ext) {
  1106. /* have only left_ext, insert length-one LC node */
  1107. insert_lc_node (btrie, ext_path, pos + TBM_STRIDE,
  1108. npbyte, 0, left_ext);
  1109. }
  1110. else {
  1111. /* have only right_ext, insert length-one LC node */
  1112. insert_lc_node (btrie, ext_path, pos + TBM_STRIDE,
  1113. npbyte, 1, right_ext);
  1114. }
  1115. }
  1116. }
  1117. btrie->n_tbm_nodes--;
  1118. free_nodes (btrie, child->tbm_node.ptr.children,
  1119. count_bits (child->tbm_node.ext_bm),
  1120. count_bits (child->tbm_node.int_bm));
  1121. }
  1122. }
  1123. assert(count_bits (int_bm) == ndata);
  1124. assert(count_bits (ext_bm) == nchildren);
  1125. node->ptr.children = alloc_nodes (btrie, nchildren, ndata);
  1126. memcpy(node->ptr.data_end - (int )ndata, data, ndata * sizeof(data[0]));
  1127. memcpy(node->ptr.children, children, nchildren * sizeof(children[0]));
  1128. node->ext_bm = ext_bm;
  1129. node->int_bm = int_bm;
  1130. btrie->n_tbm_nodes++;
  1131. }
  1132. static enum btrie_result add_to_trie(struct btrie *btrie, node_t *node,
  1133. unsigned pos, const btrie_oct_t *prefix, unsigned len, const void *data)
  1134. {
  1135. for (;;) {
  1136. if (is_lc_node (node)) {
  1137. struct lc_node *lc_node = &node->lc_node;
  1138. unsigned end = pos + lc_len (lc_node);
  1139. unsigned cbits = common_prefix (prefix + lc_shift (pos),
  1140. lc_node->prefix, (len < end ? len : end) - lc_base (pos));
  1141. unsigned clen = lc_base (pos) + cbits; /* position of first mismatch */
  1142. if (clen == end && !lc_is_terminal (lc_node)) {
  1143. /* matched entire prefix of LC node, proceed to child */
  1144. assert(lc_len (lc_node) > 0);
  1145. node = lc_node->ptr.child;
  1146. pos = end;
  1147. }
  1148. else if (clen == end && len == end && lc_is_terminal (lc_node)) {
  1149. /* exact match for terminal node - already have data for prefix */
  1150. return BTRIE_DUPLICATE_PREFIX;
  1151. }
  1152. else {
  1153. assert(clen < end || (lc_is_terminal (lc_node) && len > end));
  1154. /* Need to insert new TBM node at clen */
  1155. if (clen > pos) {
  1156. split_lc_node (btrie, lc_node, pos, clen - pos);
  1157. node = lc_node->ptr.child;
  1158. assert(is_lc_node (node));
  1159. pos = clen;
  1160. }
  1161. convert_lc_node (btrie, &node->lc_node, pos);
  1162. }
  1163. }
  1164. else if (is_empty_node (node)) {
  1165. /* at empty TBM node - just replace with terminal LC node */
  1166. init_terminal_node (btrie, node, pos, prefix, len, data);
  1167. btrie->n_entries++;
  1168. btrie->n_tbm_nodes--;
  1169. return BTRIE_OKAY;
  1170. }
  1171. else {
  1172. struct tbm_node *tbm_node = &node->tbm_node;
  1173. unsigned end = pos + TBM_STRIDE;
  1174. if (len < end) {
  1175. unsigned plen = len - pos;
  1176. unsigned pfx = extract_bits (prefix, pos, plen);
  1177. if (tbm_data_p (tbm_node, pfx, plen) != NULL)
  1178. return BTRIE_DUPLICATE_PREFIX; /* prefix already has data */
  1179. else {
  1180. tbm_insert_data (btrie, tbm_node, pfx, plen, data);
  1181. btrie->n_entries++;
  1182. return BTRIE_OKAY;
  1183. }
  1184. }
  1185. else {
  1186. unsigned pfx = extract_bits (prefix, pos, TBM_STRIDE);
  1187. /* follow extending path */
  1188. node = tbm_ext_path (tbm_node, pfx);
  1189. if (node == NULL)
  1190. node = tbm_insert_ext_path (btrie, tbm_node, pfx);
  1191. pos = end;
  1192. }
  1193. }
  1194. }
  1195. }
  1196. static const void *
  1197. search_trie(const node_t *node, unsigned pos, const btrie_oct_t *prefix,
  1198. unsigned len)
  1199. {
  1200. /* remember last TBM node seen with internal data */
  1201. const struct tbm_node *int_node = 0;
  1202. unsigned int_pfx = 0, int_plen = 0;
  1203. while (node) {
  1204. if (is_lc_node (node)) {
  1205. const struct lc_node *lc_node = &node->lc_node;
  1206. unsigned end = pos + lc_len (lc_node);
  1207. if (len < end)
  1208. break;
  1209. if (!prefixes_equal (prefix + lc_shift (pos), lc_node->prefix,
  1210. end - lc_base (pos)))
  1211. break;
  1212. if (lc_is_terminal (lc_node))
  1213. return lc_node->ptr.data; /* found terminal node */
  1214. pos = end;
  1215. node = lc_node->ptr.child;
  1216. }
  1217. else {
  1218. const struct tbm_node *tbm_node = &node->tbm_node;
  1219. unsigned end = pos + TBM_STRIDE;
  1220. if (len < end) {
  1221. unsigned plen = len - pos;
  1222. unsigned pfx = extract_bits (prefix, pos, plen);
  1223. if (has_internal_data (tbm_node, pfx, plen)) {
  1224. int_node = tbm_node;
  1225. int_pfx = pfx;
  1226. int_plen = plen;
  1227. }
  1228. break;
  1229. }
  1230. else {
  1231. unsigned pfx = extract_bits (prefix, pos, TBM_STRIDE);
  1232. if (has_internal_data (tbm_node, pfx >> 1, TBM_STRIDE - 1)) {
  1233. int_node = tbm_node;
  1234. int_pfx = pfx >> 1;
  1235. int_plen = TBM_STRIDE - 1;
  1236. }
  1237. pos = end;
  1238. node = tbm_ext_path (tbm_node, pfx);
  1239. }
  1240. }
  1241. }
  1242. if (int_node) {
  1243. const void **data_p = tbm_data_p (int_node, int_pfx, int_plen);
  1244. while (data_p == NULL) {
  1245. assert(int_plen > 0);
  1246. int_pfx >>= 1;
  1247. int_plen--;
  1248. data_p = tbm_data_p (int_node, int_pfx, int_plen);
  1249. }
  1250. return *data_p;
  1251. }
  1252. return NULL;
  1253. }
  1254. struct btrie *
  1255. btrie_init(rspamd_mempool_t *mp)
  1256. {
  1257. struct btrie *btrie;
  1258. if (!(btrie = rspamd_mempool_alloc0 (mp, sizeof(*btrie)))) {
  1259. return NULL;
  1260. }
  1261. btrie->mp = mp;
  1262. btrie->alloc_total = sizeof(*btrie);
  1263. /* count the empty root node */
  1264. btrie->n_tbm_nodes = 1;
  1265. return btrie;
  1266. }
  1267. enum btrie_result btrie_add_prefix(struct btrie *btrie,
  1268. const btrie_oct_t *prefix, unsigned len, const void *data)
  1269. {
  1270. enum btrie_result rv;
  1271. if ((rv = setjmp (btrie->exception)) != 0)
  1272. return rv; /* out of memory */
  1273. return add_to_trie (btrie, &btrie->root, 0, prefix, len, data);
  1274. }
  1275. const void *
  1276. btrie_lookup(const struct btrie *btrie, const btrie_oct_t *prefix, unsigned len)
  1277. {
  1278. return search_trie (&btrie->root, 0, prefix, len);
  1279. }
  1280. /****************************************************************
  1281. *
  1282. * btrie_stats() - statistics reporting
  1283. */
  1284. #ifdef BTRIE_EXTENDED_STATS
  1285. /* Define BTRIE_EXTENDED_STATS to get extra statistics (including
  1286. * trie depth). This statistics require a traversal of the entire trie
  1287. * to compute, and so are disabled by default.
  1288. */
  1289. struct stats {
  1290. size_t max_depth;
  1291. size_t total_depth;
  1292. #ifndef NDEBUG
  1293. size_t n_lc_nodes;
  1294. size_t n_tbm_nodes;
  1295. size_t n_entries;
  1296. size_t alloc_data;
  1297. size_t alloc_waste;
  1298. #endif
  1299. };
  1300. static void
  1301. node_stats(const node_t *node, size_t depth, struct stats *stats)
  1302. {
  1303. if (depth > stats->max_depth)
  1304. stats->max_depth = depth;
  1305. stats->total_depth += depth;
  1306. if (is_lc_node(node)) {
  1307. #ifndef NDEBUG
  1308. stats->n_lc_nodes++;
  1309. #endif
  1310. if (!lc_is_terminal(&node->lc_node))
  1311. node_stats(node->lc_node.ptr.child, depth + 1, stats);
  1312. #ifndef NDEBUG
  1313. else
  1314. stats->n_entries++;
  1315. #endif
  1316. }
  1317. else {
  1318. unsigned i;
  1319. unsigned nchildren = count_bits(node->tbm_node.ext_bm);
  1320. #ifndef NDEBUG
  1321. unsigned ndata = count_bits(node->tbm_node.int_bm);
  1322. stats->n_tbm_nodes++;
  1323. stats->n_entries += ndata;
  1324. stats->alloc_data += ndata * sizeof(void *);
  1325. stats->alloc_waste += (ndata % 2) * sizeof(void *);
  1326. #endif
  1327. for (i = 0; i < nchildren; i++)
  1328. node_stats(&node->tbm_node.ptr.children[i], depth + 1, stats);
  1329. }
  1330. }
  1331. #endif /* BTRIE_EXTENDED_STATS */
  1332. #ifndef NDEBUG
  1333. static size_t count_free(const struct btrie *btrie)
  1334. {
  1335. size_t total = 0;
  1336. unsigned sz;
  1337. for (sz = 1; sz <= MAX_CHILD_ARRAY_LEN; sz++) {
  1338. const struct free_hunk *free = btrie->free_list[sz - 1];
  1339. size_t n;
  1340. for (n = 0; free; n++)
  1341. free = free->next;
  1342. total += sz * n;
  1343. }
  1344. return total * sizeof(node_t);
  1345. }
  1346. #endif /* not NDEBUG */
  1347. const char *
  1348. btrie_stats(const struct btrie *btrie, guint duplicates)
  1349. {
  1350. static char buf[128];
  1351. size_t n_nodes = btrie->n_lc_nodes + btrie->n_tbm_nodes;
  1352. size_t alloc_free = (btrie->alloc_total + sizeof(node_t) /* do not double-count the root node */
  1353. - n_nodes * sizeof(node_t) - btrie->alloc_data - btrie->alloc_waste
  1354. - sizeof(*btrie));
  1355. #ifdef BTRIE_EXTENDED_STATS
  1356. struct stats stats;
  1357. double average_depth;
  1358. memset(&stats, 0, sizeof(stats));
  1359. node_stats(&btrie->root, 0, &stats);
  1360. average_depth = (double)stats.total_depth / n_nodes;
  1361. #ifndef NDEBUG
  1362. /* check the node counts */
  1363. assert(stats.n_lc_nodes == btrie->n_lc_nodes);
  1364. assert(stats.n_tbm_nodes == btrie->n_tbm_nodes);
  1365. assert(stats.n_entries == btrie->n_entries);
  1366. assert(stats.alloc_data == btrie->alloc_data);
  1367. assert(stats.alloc_waste == btrie->alloc_waste);
  1368. #endif /* not NDEBUG */
  1369. #endif /* BTRIE_EXTENDED_STATS */
  1370. #ifndef NDEBUG
  1371. /* check that we haven't lost any memory */
  1372. assert(alloc_free == count_free (btrie));
  1373. #endif
  1374. #ifdef BTRIE_DEBUG_ALLOC
  1375. dump_alloc_hist(btrie);
  1376. #endif
  1377. #ifdef BTRIE_EXTENDED_STATS
  1378. snprintf(buf, sizeof(buf),
  1379. "ents=%lu tbm=%lu lc=%lu mem=%.0fk free=%lu waste=%lu"
  1380. " depth=%.1f/%lu"
  1381. ,(long unsigned)btrie->n_entries, (long unsigned)btrie->n_tbm_nodes,
  1382. (long unsigned)btrie->n_lc_nodes, (double)btrie->alloc_total / 1024,
  1383. (long unsigned)alloc_free, (long unsigned)btrie->alloc_waste
  1384. , average_depth, (long unsigned)stats.max_depth);
  1385. #else
  1386. snprintf(buf, sizeof(buf),
  1387. "ents=%lu dup=%u tbm=%lu lc=%lu mem=%.0fk free=%lu waste=%lu",
  1388. (long unsigned)btrie->n_entries,
  1389. duplicates,
  1390. (long unsigned)btrie->n_tbm_nodes,
  1391. (long unsigned)btrie->n_lc_nodes, (double)btrie->alloc_total / 1024,
  1392. (long unsigned)alloc_free, (long unsigned)btrie->alloc_waste
  1393. );
  1394. #endif
  1395. buf[sizeof(buf) - 1] = '\0';
  1396. return buf;
  1397. }
  1398. /****************************************************************/
  1399. #ifndef NO_MASTER_DUMP
  1400. struct walk_context
  1401. {
  1402. btrie_walk_cb_t *callback;
  1403. void *user_data;
  1404. btrie_oct_t prefix[(BTRIE_MAX_PREFIX + 7) / 8];
  1405. };
  1406. static void
  1407. walk_node(const node_t *node, unsigned pos, struct walk_context *ctx);
  1408. static void walk_tbm_node(const struct tbm_node *node, unsigned pos,
  1409. unsigned pfx, unsigned plen, struct walk_context *ctx)
  1410. {
  1411. btrie_oct_t *prefix = ctx->prefix;
  1412. int pbyte = pos / 8;
  1413. btrie_oct_t pbit = 0x80 >> (pos % 8);
  1414. const void **data_p = tbm_data_p (node, pfx, plen);
  1415. if (pos >= BTRIE_MAX_PREFIX) {
  1416. /* This can/should not happen, but don't overwrite buffers if it does. */
  1417. return;
  1418. }
  1419. if (data_p)
  1420. ctx->callback (prefix, pos, *data_p, 0, ctx->user_data);
  1421. /* walk children */
  1422. if (plen < TBM_STRIDE - 1) {
  1423. /* children are internal prefixes in same node */
  1424. walk_tbm_node (node, pos + 1, pfx << 1, plen + 1, ctx);
  1425. prefix[pbyte] |= pbit;
  1426. walk_tbm_node (node, pos + 1, (pfx << 1) + 1, plen + 1, ctx);
  1427. prefix[pbyte] &= ~pbit;
  1428. }
  1429. else {
  1430. /* children are extending paths */
  1431. const node_t *ext_path;
  1432. if ((ext_path = tbm_ext_path (node, pfx << 1)) != NULL)
  1433. walk_node (ext_path, pos + 1, ctx);
  1434. if ((ext_path = tbm_ext_path (node, (pfx << 1) + 1)) != NULL) {
  1435. prefix[pbyte] |= pbit;
  1436. walk_node (ext_path, pos + 1, ctx);
  1437. prefix[pbyte] &= ~pbit;
  1438. }
  1439. }
  1440. if (data_p)
  1441. ctx->callback (prefix, pos, *data_p, 1, ctx->user_data);
  1442. }
  1443. static void walk_lc_node(const struct lc_node *node, unsigned pos,
  1444. struct walk_context *ctx)
  1445. {
  1446. btrie_oct_t *prefix = ctx->prefix;
  1447. unsigned end = pos + lc_len (node);
  1448. btrie_oct_t save_prefix = prefix[lc_shift (pos)];
  1449. if (end > BTRIE_MAX_PREFIX) {
  1450. /* This can/should not happen, but don't overwrite buffers if it does. */
  1451. return;
  1452. }
  1453. /* construct full prefix to node */
  1454. memcpy(&prefix[lc_shift (pos)], node->prefix, lc_bytes (node, pos));
  1455. if (end % 8)
  1456. prefix[end / 8] &= high_bits (end % 8);
  1457. if (lc_is_terminal (node)) {
  1458. ctx->callback (prefix, end, node->ptr.data, 0, ctx->user_data);
  1459. ctx->callback (prefix, end, node->ptr.data, 1, ctx->user_data);
  1460. }
  1461. else
  1462. walk_node (node->ptr.child, end, ctx);
  1463. prefix[lc_shift (pos)] = save_prefix; /* restore parents prefix */
  1464. if (lc_bytes (node, pos) > 1)
  1465. memset(&prefix[lc_shift (pos) + 1], 0, lc_bytes (node, pos) - 1);
  1466. }
  1467. static void walk_node(const node_t *node, unsigned pos,
  1468. struct walk_context *ctx)
  1469. {
  1470. if (is_lc_node (node))
  1471. walk_lc_node (&node->lc_node, pos, ctx);
  1472. else
  1473. walk_tbm_node (&node->tbm_node, pos, 0, 0, ctx);
  1474. }
  1475. /* walk trie in lexicographical order
  1476. *
  1477. * calls callback twice (once preorder, once postorder) at each prefix
  1478. */
  1479. void btrie_walk(const struct btrie *btrie, btrie_walk_cb_t *callback,
  1480. void *user_data)
  1481. {
  1482. struct walk_context ctx;
  1483. memset(&ctx, 0, sizeof(ctx));
  1484. ctx.callback = callback;
  1485. ctx.user_data = user_data;
  1486. walk_node (&btrie->root, 0, &ctx);
  1487. }
  1488. #endif /* not NO_MASTER_DUMP */
  1489. #ifdef TEST
  1490. /*****************************************************************
  1491. *
  1492. * Unit tests
  1493. *
  1494. */
  1495. #include <stdio.h>
  1496. #ifndef UNUSED
  1497. # define UNUSED __attribute__((unused))
  1498. #endif
  1499. /* bogus replacements mp_alloc for running self-tests */
  1500. void *
  1501. mp_alloc(UNUSED struct mempool *mp, unsigned sz, UNUSED int align)
  1502. {
  1503. return malloc(sz);
  1504. }
  1505. #if 0
  1506. # define PASS(name) puts("OK " name)
  1507. #else
  1508. # define PASS(name) fputs(".", stdout); fflush(stdout)
  1509. #endif
  1510. const char * pgm_name = "???";
  1511. static void
  1512. test_struct_node_packing()
  1513. {
  1514. node_t node;
  1515. assert(sizeof(struct tbm_node) == 2 * sizeof(void *));
  1516. assert(sizeof(struct lc_node) == 2 * sizeof(void *));
  1517. assert(sizeof(node_t) == 2 * sizeof(void *));
  1518. /* The lc_node bit must be an alias for bit zero of int_bm, since
  1519. * that is the only unused bit in the TBM node structure.
  1520. */
  1521. memset(&node, 0, sizeof(node));
  1522. assert(node.tbm_node.int_bm == 0);
  1523. lc_init_flags(&node.lc_node, 0, 0);
  1524. assert(node.tbm_node.int_bm == bit(0));
  1525. PASS("test_struct_node_packing");
  1526. }
  1527. static void
  1528. test_bit()
  1529. {
  1530. tbm_bitmap_t ones = ~(tbm_bitmap_t)0;
  1531. tbm_bitmap_t high_bit = ones ^ (ones >> 1);
  1532. assert(bit(0) == high_bit);
  1533. assert(bit(1) == high_bit >> 1);
  1534. assert(bit(8 * sizeof(tbm_bitmap_t) - 1) == 1);
  1535. PASS("test_bit");
  1536. }
  1537. static void
  1538. test_count_bits()
  1539. {
  1540. unsigned max_bits = sizeof(tbm_bitmap_t) * 8;
  1541. tbm_bitmap_t ones = ~(tbm_bitmap_t)0;
  1542. assert(count_bits(0) == 0);
  1543. assert(count_bits(1) == 1);
  1544. assert(count_bits(2) == 1);
  1545. assert(count_bits(3) == 2);
  1546. assert(count_bits(ones) == max_bits);
  1547. assert(count_bits(~1) == max_bits - 1);
  1548. /* count_bits(0x5555....) */
  1549. assert(count_bits(ones / 3) == max_bits / 2);
  1550. /* count_bits(0x3333...) */
  1551. assert(count_bits(ones / 5) == max_bits / 2);
  1552. /* count_bits(0x0f0f...) */
  1553. assert(count_bits(ones / 17) == max_bits / 2);
  1554. /* count_bits(0x1010...) */
  1555. assert(count_bits(ones / 255) == max_bits / 8);
  1556. PASS("test_count_bits");
  1557. }
  1558. static void
  1559. test_count_bits_before()
  1560. {
  1561. unsigned max_bits = sizeof(tbm_bitmap_t) * 8;
  1562. tbm_bitmap_t ones = ~(tbm_bitmap_t)0;
  1563. unsigned i;
  1564. for (i = 0; i < max_bits; i++) {
  1565. assert(count_bits_before(0, i) == 0);
  1566. assert(count_bits_before(ones, i) == i);
  1567. }
  1568. PASS("test_count_bits_before");
  1569. }
  1570. static void
  1571. test_count_bits_from()
  1572. {
  1573. unsigned max_bits = sizeof(tbm_bitmap_t) * 8;
  1574. tbm_bitmap_t ones = ~(tbm_bitmap_t)0;
  1575. unsigned i;
  1576. for (i = 0; i < max_bits; i++) {
  1577. assert(count_bits_from(0, i) == 0);
  1578. assert(count_bits_from(ones, i) == max_bits - i);
  1579. }
  1580. PASS("test_count_bits_from");
  1581. }
  1582. static void
  1583. test_extract_bits()
  1584. {
  1585. static btrie_oct_t prefix[] = {0xff, 0x55, 0xaa, 0x00};
  1586. unsigned i;
  1587. for (i = 0; i < 32; i++)
  1588. assert(extract_bits(prefix, i, 0) == 0);
  1589. for (i = 0; i < 8; i++)
  1590. assert(extract_bits(prefix, i, 1) == 1);
  1591. for (i = 8; i < 16; i++)
  1592. assert(extract_bits(prefix, i, 1) == i % 2);
  1593. for (i = 16; i < 24; i++)
  1594. assert(extract_bits(prefix, i, 1) == (i + 1) % 2);
  1595. for (i = 24; i < 32; i++)
  1596. assert(extract_bits(prefix, i, 1) == 0);
  1597. assert(extract_bits(prefix, 2, 6) == 0x3f);
  1598. assert(extract_bits(prefix, 3, 6) == 0x3e);
  1599. assert(extract_bits(prefix, 4, 6) == 0x3d);
  1600. assert(extract_bits(prefix, 5, 6) == 0x3a);
  1601. assert(extract_bits(prefix, 6, 6) == 0x35);
  1602. assert(extract_bits(prefix, 7, 6) == 0x2a);
  1603. assert(extract_bits(prefix, 8, 6) == 0x15);
  1604. PASS("test_extract_bits");
  1605. }
  1606. static void
  1607. test_high_bits()
  1608. {
  1609. assert(high_bits(0) == 0x00);
  1610. assert(high_bits(1) == 0x80);
  1611. assert(high_bits(2) == 0xc0);
  1612. assert(high_bits(3) == 0xe0);
  1613. assert(high_bits(4) == 0xf0);
  1614. assert(high_bits(5) == 0xf8);
  1615. assert(high_bits(6) == 0xfc);
  1616. assert(high_bits(7) == 0xfe);
  1617. assert(high_bits(8) == 0xff);
  1618. PASS("test_high_bits");
  1619. }
  1620. static void
  1621. test_prefixes_equal()
  1622. {
  1623. btrie_oct_t prefix1[LC_BYTES_PER_NODE];
  1624. btrie_oct_t prefix2[LC_BYTES_PER_NODE];
  1625. unsigned i;
  1626. memset(prefix1, 0xaa, LC_BYTES_PER_NODE);
  1627. memset(prefix2, 0xaa, LC_BYTES_PER_NODE);
  1628. for (i = 0; i < 8 * LC_BYTES_PER_NODE; i++) {
  1629. assert(prefixes_equal(prefix1, prefix2, i));
  1630. prefix1[i / 8] ^= 1 << (7 - i % 8);
  1631. assert(!prefixes_equal(prefix1, prefix2, 8 * LC_BYTES_PER_NODE));
  1632. assert(prefixes_equal(prefix1, prefix2, i));
  1633. if (i + 1 < 8 * LC_BYTES_PER_NODE)
  1634. assert(!prefixes_equal(prefix1, prefix2, i + 1));
  1635. prefix1[i / 8] ^= 1 << (7 - i % 8);
  1636. }
  1637. PASS("test_prefixes_equal");
  1638. }
  1639. static void
  1640. test_common_prefix()
  1641. {
  1642. btrie_oct_t prefix1[LC_BYTES_PER_NODE];
  1643. btrie_oct_t prefix2[LC_BYTES_PER_NODE];
  1644. unsigned i;
  1645. memset(prefix1, 0x55, LC_BYTES_PER_NODE);
  1646. memset(prefix2, 0x55, LC_BYTES_PER_NODE);
  1647. for (i = 0; i < 8 * LC_BYTES_PER_NODE; i++) {
  1648. assert(common_prefix(prefix1, prefix2, i) == i);
  1649. prefix1[i / 8] ^= 1 << (7 - i % 8);
  1650. assert(common_prefix(prefix1, prefix2, 8 * LC_BYTES_PER_NODE) == i);
  1651. if (i + 1 < 8 * LC_BYTES_PER_NODE)
  1652. assert(common_prefix(prefix1, prefix2, i+1) == i);
  1653. prefix1[i / 8] ^= 1 << (7 - i % 8);
  1654. }
  1655. PASS("test_common_prefix");
  1656. }
  1657. static void
  1658. test_base_index()
  1659. {
  1660. assert(base_index(0,0) == 1);
  1661. assert(base_index(0,1) == 2);
  1662. assert(base_index(1,1) == 3);
  1663. assert(base_index(0,2) == 4);
  1664. assert(base_index(1,2) == 5);
  1665. assert(base_index(2,2) == 6);
  1666. assert(base_index(3,2) == 7);
  1667. PASS("test_base_index");
  1668. }
  1669. static void
  1670. test_has_internal_data()
  1671. {
  1672. struct tbm_node node;
  1673. unsigned plen, pfx, bi;
  1674. for (plen = 0; plen < TBM_STRIDE; plen++) {
  1675. for (pfx = 0; pfx < 1U << plen; pfx++) {
  1676. tbm_bitmap_t ancestor_mask = 0;
  1677. for (bi = base_index(pfx, plen); bi; bi >>= 1) {
  1678. node.int_bm = bit(bi);
  1679. ancestor_mask |= bit(bi);
  1680. assert(has_internal_data(&node, pfx, plen));
  1681. }
  1682. node.int_bm = ~ancestor_mask;
  1683. assert(!has_internal_data(&node, pfx, plen));
  1684. }
  1685. }
  1686. PASS("test_has_internal_data");
  1687. }
  1688. /****************************************************************/
  1689. static const btrie_oct_t numbered_bytes[] = {
  1690. 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
  1691. 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
  1692. 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
  1693. 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
  1694. 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
  1695. 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
  1696. 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
  1697. 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
  1698. };
  1699. static void
  1700. check_non_terminal_lc_node(struct lc_node *node, unsigned len)
  1701. {
  1702. assert(is_lc_node((node_t *)node));
  1703. assert(!lc_is_terminal(node));
  1704. assert(lc_len(node) == len);
  1705. }
  1706. static void
  1707. check_terminal_lc_node(struct lc_node *node, unsigned len, const void *data)
  1708. {
  1709. assert(is_lc_node((node_t *)node));
  1710. assert(lc_is_terminal(node));
  1711. assert(lc_len(node) == len);
  1712. assert(node->ptr.data == data);
  1713. }
  1714. static void
  1715. test_init_terminal_node()
  1716. {
  1717. struct btrie *btrie = btrie_init(NULL);
  1718. const void *data = (void *)0xdeadbeef;
  1719. node_t node;
  1720. struct lc_node *head = &node.lc_node;
  1721. init_terminal_node(btrie, &node, 0,
  1722. numbered_bytes, 8 * LC_BYTES_PER_NODE, data);
  1723. check_terminal_lc_node(head, 8 * LC_BYTES_PER_NODE, data);
  1724. assert(memcmp(head->prefix, numbered_bytes, LC_BYTES_PER_NODE) == 0);
  1725. init_terminal_node(btrie, &node, 7,
  1726. numbered_bytes, 8 * LC_BYTES_PER_NODE, data);
  1727. check_terminal_lc_node(head, 8 * LC_BYTES_PER_NODE - 7, data);
  1728. assert(memcmp(head->prefix, numbered_bytes, LC_BYTES_PER_NODE) == 0);
  1729. init_terminal_node(btrie, &node, 0,
  1730. numbered_bytes, 2 * 8 * LC_BYTES_PER_NODE, data);
  1731. check_non_terminal_lc_node(head, 8 * LC_BYTES_PER_NODE);
  1732. assert(memcmp(head->prefix, numbered_bytes, LC_BYTES_PER_NODE) == 0);
  1733. {
  1734. struct lc_node *child = &head->ptr.child->lc_node;
  1735. check_terminal_lc_node(child, 8 * LC_BYTES_PER_NODE, data);
  1736. assert(memcmp(child->prefix, &numbered_bytes[LC_BYTES_PER_NODE],
  1737. LC_BYTES_PER_NODE) == 0);
  1738. }
  1739. init_terminal_node(btrie, &node, 15,
  1740. numbered_bytes, 8 * LC_BYTES_PER_NODE + 15, data);
  1741. check_non_terminal_lc_node(head, 8 * LC_BYTES_PER_NODE - 7);
  1742. assert(memcmp(head->prefix, &numbered_bytes[1], LC_BYTES_PER_NODE) == 0);
  1743. {
  1744. struct lc_node *child = &head->ptr.child->lc_node;
  1745. check_terminal_lc_node(child, 7, data);
  1746. assert(child->prefix[0] == numbered_bytes[LC_BYTES_PER_NODE + 1]);
  1747. }
  1748. PASS("test_init_terminal_node");
  1749. }
  1750. static void
  1751. test_coalesce_lc_node()
  1752. {
  1753. struct btrie *btrie = btrie_init(NULL);
  1754. const void *data = (void *)0xdeadbeef;
  1755. node_t node;
  1756. struct lc_node *head = &node.lc_node;
  1757. /* test merging */
  1758. init_terminal_node(btrie, &node, 0,
  1759. numbered_bytes, 8 * (LC_BYTES_PER_NODE + 1), data);
  1760. check_non_terminal_lc_node(head, LC_BYTES_PER_NODE * 8);
  1761. lc_add_to_len(head, -8);
  1762. coalesce_lc_node(btrie, head, 8);
  1763. check_terminal_lc_node(head, LC_BYTES_PER_NODE * 8, data);
  1764. assert(head->prefix[LC_BYTES_PER_NODE - 1]
  1765. == numbered_bytes[LC_BYTES_PER_NODE]);
  1766. /* test bit stealing */
  1767. init_terminal_node(btrie, &node, 0,
  1768. numbered_bytes, 8 * (2 * LC_BYTES_PER_NODE), data);
  1769. check_non_terminal_lc_node(head, LC_BYTES_PER_NODE * 8);
  1770. lc_add_to_len(head, -15);
  1771. coalesce_lc_node(btrie, head, 15);
  1772. check_non_terminal_lc_node(head, LC_BYTES_PER_NODE * 8 - 7);
  1773. assert(memcmp(head->prefix, numbered_bytes, LC_BYTES_PER_NODE - 1) == 0);
  1774. assert(head->prefix[LC_BYTES_PER_NODE - 1]
  1775. == numbered_bytes[LC_BYTES_PER_NODE]);
  1776. {
  1777. struct lc_node *child = &head->ptr.child->lc_node;
  1778. check_terminal_lc_node(child, 8 * (LC_BYTES_PER_NODE - 1), data);
  1779. assert(memcmp(child->prefix, &numbered_bytes[LC_BYTES_PER_NODE + 1],
  1780. LC_BYTES_PER_NODE - 1) == 0);
  1781. }
  1782. PASS("test_coalesce_lc_node");
  1783. }
  1784. static void
  1785. test_shorten_lc_node()
  1786. {
  1787. struct btrie *btrie = btrie_init(NULL);
  1788. const void *data = (void *)0xdeadbeef;
  1789. node_t node, shorter;
  1790. /* test shorten without shift */
  1791. init_terminal_node(btrie, &node, 0,
  1792. numbered_bytes, 8 * LC_BYTES_PER_NODE, data);
  1793. memset(shorter.lc_node.prefix, 0xff, LC_BYTES_PER_NODE);
  1794. shorten_lc_node(btrie, &shorter, 7, &node.lc_node, 0);
  1795. check_terminal_lc_node(&shorter.lc_node, LC_BYTES_PER_NODE * 8 - 7, data);
  1796. assert(memcmp(shorter.lc_node.prefix, numbered_bytes, LC_BYTES_PER_NODE)
  1797. == 0);
  1798. /* test shorten with shift */
  1799. init_terminal_node(btrie, &node, 7,
  1800. numbered_bytes, 8 * LC_BYTES_PER_NODE, data);
  1801. memset(shorter.lc_node.prefix, 0xff, LC_BYTES_PER_NODE);
  1802. shorten_lc_node(btrie, &shorter, 9, &node.lc_node, 7);
  1803. check_terminal_lc_node(&shorter.lc_node, LC_BYTES_PER_NODE * 8 - 9, data);
  1804. assert(memcmp(shorter.lc_node.prefix, &numbered_bytes[1],
  1805. LC_BYTES_PER_NODE - 1) == 0);
  1806. {
  1807. /* test child stealing */
  1808. struct lc_node head;
  1809. node_t tail, shorter;
  1810. lc_init_flags(&head, 0, 7);
  1811. head.ptr.child = &tail;
  1812. init_empty_node(btrie, &tail);
  1813. shorten_lc_node(btrie, &shorter, 7, &head, 0);
  1814. assert(is_empty_node(&shorter));
  1815. }
  1816. PASS("test_shorten_lc_node");
  1817. }
  1818. static void
  1819. test_split_lc_node()
  1820. {
  1821. struct btrie *btrie = btrie_init(NULL);
  1822. const void *data = (void *)0xdeadbeef;
  1823. struct lc_node node;
  1824. init_terminal_node(btrie, (node_t *)&node, 1, numbered_bytes, 25, data);
  1825. split_lc_node(btrie, &node, 1, 8);
  1826. check_non_terminal_lc_node(&node, 8);
  1827. check_terminal_lc_node(&node.ptr.child->lc_node, 16, data);
  1828. /* test conversion of terminal to non-terminal */
  1829. init_terminal_node(btrie, (node_t *)&node, 7, numbered_bytes, 10, data);
  1830. split_lc_node(btrie, &node, 7, 3);
  1831. check_non_terminal_lc_node(&node, 3);
  1832. check_terminal_lc_node(&node.ptr.child->lc_node, 0, data);
  1833. PASS("test_split_lc_node");
  1834. }
  1835. static void
  1836. test_convert_lc_node_1()
  1837. {
  1838. struct btrie *btrie = btrie_init(NULL);
  1839. const void *data = (void *)0xdeadbeef;
  1840. struct lc_node head;
  1841. /* test tail is left */
  1842. lc_init_flags(&head, 0, 1);
  1843. head.prefix[0] = 0;
  1844. head.ptr.child = alloc_nodes(btrie, 1, 0);
  1845. init_terminal_node(btrie, head.ptr.child, 1, numbered_bytes, 1, data);
  1846. convert_lc_node_1(btrie, &head, 0);
  1847. {
  1848. node_t *result = (node_t *)&head;
  1849. assert(is_tbm_node(result));
  1850. assert(result->tbm_node.ext_bm == 0);
  1851. assert(result->tbm_node.int_bm == bit(base_index(0, 1)));
  1852. assert(*tbm_data_p(&result->tbm_node, 0, 1) == data);
  1853. }
  1854. /* test tail is right */
  1855. lc_init_flags(&head, 0, 1);
  1856. head.prefix[0] = 1;
  1857. head.ptr.child = alloc_nodes(btrie, 1, 0);
  1858. init_terminal_node(btrie, head.ptr.child, 8, numbered_bytes, 10, data);
  1859. convert_lc_node_1(btrie, &head, 7);
  1860. {
  1861. node_t *result = (node_t *)&head;
  1862. assert(is_tbm_node(result));
  1863. assert(result->tbm_node.ext_bm == 0);
  1864. assert(result->tbm_node.int_bm == bit(base_index(4, 3)));
  1865. assert(*tbm_data_p(&result->tbm_node, 4, 3) == data);
  1866. }
  1867. PASS("test_convert_lc_node_1");
  1868. }
  1869. static void
  1870. test_convert_lc_node()
  1871. {
  1872. struct btrie *btrie = btrie_init(NULL);
  1873. const void *data = (void *)0xdeadbeef;
  1874. node_t node;
  1875. /* if (len >= TBM_STRIDE) */
  1876. init_terminal_node(btrie, &node, 7, numbered_bytes, TBM_STRIDE + 7, data);
  1877. convert_lc_node(btrie, &node.lc_node, 7);
  1878. assert(is_tbm_node(&node));
  1879. assert(node.tbm_node.ext_bm == bit(0));
  1880. assert(node.tbm_node.int_bm == 0);
  1881. check_terminal_lc_node(&tbm_ext_path(&node.tbm_node, 0)->lc_node, 0, data);
  1882. /* if (lc_is_terminal(node)) */
  1883. init_terminal_node(btrie, &node, 0, numbered_bytes, 0, data);
  1884. convert_lc_node(btrie, &node.lc_node, 0);
  1885. assert(is_tbm_node(&node));
  1886. assert(node.tbm_node.ext_bm == 0);
  1887. assert(node.tbm_node.int_bm == bit(base_index(0, 0)));
  1888. assert(*tbm_data_p(&node.tbm_node, 0, 0) == data);
  1889. /* else */
  1890. lc_init_flags(&node.lc_node, 0, TBM_STRIDE - 1);
  1891. node.lc_node.prefix[0] = 0;
  1892. node.lc_node.ptr.child = alloc_nodes(btrie, 1, 0);
  1893. init_empty_node(btrie, node.lc_node.ptr.child);
  1894. tbm_insert_data(btrie, &node.lc_node.ptr.child->tbm_node, 0, 0, data);
  1895. convert_lc_node(btrie, &node.lc_node, 0);
  1896. assert(is_tbm_node(&node));
  1897. assert(node.tbm_node.ext_bm == 0);
  1898. assert(node.tbm_node.int_bm == bit(base_index(0, TBM_STRIDE - 1)));
  1899. assert(*tbm_data_p(&node.tbm_node, 0, TBM_STRIDE - 1) == data);
  1900. PASS("test_convert_lc_node");
  1901. }
  1902. static void
  1903. test_insert_lc_node()
  1904. {
  1905. struct btrie *btrie = btrie_init(NULL);
  1906. const void *data = (void *)0xdeadbeef;
  1907. node_t node, tail;
  1908. /* test optimized case, last_bit == 0 */
  1909. init_terminal_node(btrie, &tail, 9, numbered_bytes, 17, data);
  1910. insert_lc_node(btrie, &node, 8, 0, 0, &tail);
  1911. check_terminal_lc_node(&node.lc_node, 9, data);
  1912. assert(memcmp(node.lc_node.prefix, &numbered_bytes[1], 2) == 0);
  1913. /* test optimized case, last_bit == 1 */
  1914. init_terminal_node(btrie, &tail, 7, &numbered_bytes[0x12], 15, data);
  1915. insert_lc_node(btrie, &node, 6, 0x10, 1, &tail);
  1916. check_terminal_lc_node(&node.lc_node, 9, data);
  1917. assert(node.lc_node.prefix[0] == 0x12);
  1918. assert(node.lc_node.prefix[1] == 0x13);
  1919. /* test with shift */
  1920. init_terminal_node(btrie, &tail, 0, numbered_bytes, 8, data);
  1921. insert_lc_node(btrie, &node, 7, 0x40, 1, &tail);
  1922. check_terminal_lc_node(&node.lc_node, 9, data);
  1923. assert(node.lc_node.prefix[0] == 0x41);
  1924. assert(node.lc_node.prefix[1] == numbered_bytes[0]);
  1925. /* test with TBM node */
  1926. init_empty_node(btrie, &tail);
  1927. insert_lc_node(btrie, &node, 6, 0x40, 0, &tail);
  1928. check_non_terminal_lc_node(&node.lc_node, 1);
  1929. assert(is_tbm_node(node.lc_node.ptr.child));
  1930. PASS("test_insert_lc_node");
  1931. }
  1932. static void
  1933. test_next_pbyte()
  1934. {
  1935. assert(next_pbyte(0xff, 0, 1) == 0x80 >> (TBM_STRIDE - 1));
  1936. assert(next_pbyte(0xff, 1, 1) == (0x80 | (0x80 >> TBM_STRIDE)));
  1937. assert(next_pbyte(0xff, 2, 1) == (0xc0 | (0x80 >> (TBM_STRIDE + 1))));
  1938. assert(next_pbyte(0xff, 8 - TBM_STRIDE, 1) == 0);
  1939. assert(next_pbyte(0xff, 9 - TBM_STRIDE, 1) == 0x80);
  1940. PASS("test_next_pbyte");
  1941. }
  1942. static void
  1943. test_init_tbm_node()
  1944. {
  1945. struct btrie *btrie = btrie_init(NULL);
  1946. const void *data = (void *)0xdeadbeef;
  1947. unsigned lr;
  1948. node_t node;
  1949. /* test root data */
  1950. init_tbm_node(btrie, &node, 0, 0, &data, NULL, NULL);
  1951. assert(is_tbm_node(&node));
  1952. assert(node.tbm_node.ext_bm == 0);
  1953. assert(node.tbm_node.int_bm == bit(base_index(0, 0)));
  1954. assert(*tbm_data_p(&node.tbm_node, 0, 0) == data);
  1955. for (lr = 0; lr < 2; lr++) {
  1956. node_t child;
  1957. node_t *left = lr ? NULL : &child;
  1958. node_t *right = lr ? &child : NULL;
  1959. unsigned base = lr ? (1U << (TBM_STRIDE - 1)) : 0;
  1960. unsigned pfx;
  1961. /* test with long LC node child */
  1962. init_terminal_node(btrie, &child, 1, numbered_bytes, TBM_STRIDE + 1, data);
  1963. init_tbm_node(btrie, &node, 0, 0, NULL, left, right);
  1964. assert(is_tbm_node(&node));
  1965. assert(node.tbm_node.ext_bm == bit(base));
  1966. assert(node.tbm_node.int_bm == 0);
  1967. check_terminal_lc_node(&tbm_ext_path(&node.tbm_node, base)->lc_node,
  1968. 1, data);
  1969. /* test with short LC node children */
  1970. init_terminal_node(btrie, &child, 1, numbered_bytes, TBM_STRIDE - 1, data);
  1971. init_tbm_node(btrie, &node, 0, 0, NULL, left, right);
  1972. assert(is_tbm_node(&node));
  1973. assert(node.tbm_node.ext_bm == 0);
  1974. assert(node.tbm_node.int_bm == bit(base_index(base >> 1, TBM_STRIDE-1)));
  1975. assert(*tbm_data_p(&node.tbm_node, base >> 1, TBM_STRIDE-1) == data);
  1976. /* construct TBM node with all eight combinations of having data,
  1977. * left_ext and/or right_ext in its extending paths */
  1978. init_empty_node(btrie, &child);
  1979. for (pfx = 0; pfx < 8; pfx++) {
  1980. if (pfx & 1)
  1981. tbm_insert_data(btrie, &child.tbm_node, pfx, TBM_STRIDE - 1, data);
  1982. if (pfx & 2) {
  1983. btrie_oct_t prefix0 = 0;
  1984. init_terminal_node(btrie,
  1985. tbm_insert_ext_path(btrie, &child.tbm_node, 2*pfx),
  1986. TBM_STRIDE + 1,
  1987. &prefix0, TBM_STRIDE + 2, data);
  1988. }
  1989. if (pfx & 4) {
  1990. btrie_oct_t prefix0 = 0x80 >> TBM_STRIDE;
  1991. init_terminal_node(btrie,
  1992. tbm_insert_ext_path(btrie, &child.tbm_node, 2*pfx+1),
  1993. TBM_STRIDE + 1,
  1994. &prefix0, TBM_STRIDE + 3, data);
  1995. }
  1996. }
  1997. init_tbm_node(btrie, &node, 0, 0, NULL, left, right);
  1998. for (pfx = 0; pfx < 8; pfx++) {
  1999. unsigned base = lr ? (1U << (TBM_STRIDE - 1)) : 0;
  2000. node_t *ext_path = tbm_ext_path(&node.tbm_node, base + pfx);
  2001. if (pfx == 0)
  2002. assert(ext_path == NULL);
  2003. else if (pfx == 1)
  2004. check_terminal_lc_node(&ext_path->lc_node, 0, data);
  2005. else if (pfx == 2) {
  2006. check_terminal_lc_node(&ext_path->lc_node, 2, data);
  2007. assert(ext_path->lc_node.prefix[0] == 0);
  2008. }
  2009. else if (pfx == 4) {
  2010. check_terminal_lc_node(&ext_path->lc_node, 3, data);
  2011. assert(ext_path->lc_node.prefix[0] == (0x80 >> TBM_STRIDE));
  2012. }
  2013. else {
  2014. tbm_bitmap_t int_bm = 0;
  2015. assert(is_tbm_node(ext_path));
  2016. if (pfx & 1) {
  2017. int_bm |= bit(base_index(0, 0));
  2018. assert(*tbm_data_p(&ext_path->tbm_node, 0, 0) == data);
  2019. }
  2020. if (pfx & 2) {
  2021. int_bm |= bit(base_index(0, 2));
  2022. assert(*tbm_data_p(&ext_path->tbm_node, 0, 2) == data);
  2023. }
  2024. if (pfx & 4) {
  2025. int_bm |= bit(base_index(4, 3));
  2026. assert(*tbm_data_p(&ext_path->tbm_node, 4, 3) == data);
  2027. }
  2028. assert(ext_path->tbm_node.int_bm == int_bm);
  2029. }
  2030. }
  2031. }
  2032. PASS("test_init_tbm_node");
  2033. }
  2034. static void
  2035. test_add_to_trie()
  2036. {
  2037. struct btrie *btrie = btrie_init(NULL);
  2038. const void *data = (void *)0xdeadbeef;
  2039. enum btrie_result result;
  2040. unsigned pfx, plen;
  2041. node_t root;
  2042. /* test initial insertion */
  2043. init_empty_node(btrie, &root);
  2044. result = add_to_trie(btrie, &root, 0,
  2045. numbered_bytes, 8 * 2 * LC_BYTES_PER_NODE, data);
  2046. assert(result == BTRIE_OKAY);
  2047. check_non_terminal_lc_node(&root.lc_node, 8 * LC_BYTES_PER_NODE);
  2048. check_terminal_lc_node(&root.lc_node.ptr.child->lc_node,
  2049. 8 * LC_BYTES_PER_NODE, data);
  2050. /* test can follow LC node to tail, and then detect duplicate prefix */
  2051. result = add_to_trie(btrie, &root, 0,
  2052. numbered_bytes, 8 * 2 * LC_BYTES_PER_NODE, data);
  2053. assert(result == BTRIE_DUPLICATE_PREFIX);
  2054. /* test can insert new TBM node within existing LC node */
  2055. result = add_to_trie(btrie, &root, 0,
  2056. &numbered_bytes[1], 16, data);
  2057. assert(result == BTRIE_OKAY);
  2058. check_non_terminal_lc_node(&root.lc_node, 7);
  2059. assert(is_tbm_node(root.lc_node.ptr.child));
  2060. /* test can convert terminal LC node to TBM node */
  2061. init_terminal_node(btrie, &root, 0, numbered_bytes, 12, data);
  2062. result = add_to_trie(btrie, &root, 0, numbered_bytes, 24, data);
  2063. assert(result == BTRIE_OKAY);
  2064. check_non_terminal_lc_node(&root.lc_node, 12);
  2065. assert(is_tbm_node(root.lc_node.ptr.child));
  2066. /* test can insert internal prefix data in TBM node */
  2067. for (plen = 0; plen < TBM_STRIDE; plen++) {
  2068. for (pfx = 0; pfx < (1U << plen); pfx++) {
  2069. btrie_oct_t prefix0 = plen ? pfx << (8 - plen) : 0;
  2070. init_empty_node(btrie, &root);
  2071. init_terminal_node(btrie, tbm_insert_ext_path(btrie, &root.tbm_node, 0),
  2072. TBM_STRIDE,
  2073. numbered_bytes, 8, data);
  2074. result = add_to_trie(btrie, &root, 0, &prefix0, plen, data);
  2075. assert(result == BTRIE_OKAY);
  2076. assert(is_tbm_node(&root));
  2077. assert(root.tbm_node.ext_bm == bit(0));
  2078. assert(root.tbm_node.int_bm == bit(base_index(pfx, plen)));
  2079. assert(*tbm_data_p(&root.tbm_node, pfx, plen) == data);
  2080. result = add_to_trie(btrie, &root, 0, &prefix0, plen, data);
  2081. assert(result == BTRIE_DUPLICATE_PREFIX);
  2082. }
  2083. }
  2084. /* test can add extending paths to TBM node */
  2085. for (pfx = 0; pfx < (1U << TBM_STRIDE); pfx++) {
  2086. btrie_oct_t prefix0 = pfx << (8 - TBM_STRIDE);
  2087. init_empty_node(btrie, &root);
  2088. tbm_insert_data(btrie, &root.tbm_node, 0, 0, data);
  2089. result = add_to_trie(btrie, &root, 0, &prefix0, 8, data);
  2090. assert(result == BTRIE_OKAY);
  2091. assert(is_tbm_node(&root));
  2092. assert(root.tbm_node.ext_bm == bit(pfx));
  2093. assert(root.tbm_node.int_bm == bit(base_index(0, 0)));
  2094. check_terminal_lc_node(&tbm_ext_path(&root.tbm_node, pfx)->lc_node,
  2095. 8 - TBM_STRIDE, data);
  2096. result = add_to_trie(btrie, &root, 0, &prefix0, 8, data);
  2097. assert(result == BTRIE_DUPLICATE_PREFIX);
  2098. }
  2099. /* test can follow extending path */
  2100. init_empty_node(btrie, &root);
  2101. init_terminal_node(btrie,
  2102. tbm_insert_ext_path(btrie, &root.tbm_node, 0), TBM_STRIDE,
  2103. numbered_bytes, 8, data);
  2104. result = add_to_trie(btrie, &root, 0, numbered_bytes, 7, data);
  2105. assert(result == BTRIE_OKAY);
  2106. assert(root.tbm_node.ext_bm == bit(0));
  2107. assert(root.tbm_node.int_bm == 0);
  2108. check_non_terminal_lc_node(&root.tbm_node.ptr.children[0].lc_node,
  2109. 7 - TBM_STRIDE);
  2110. PASS("test_add_to_trie");
  2111. }
  2112. static void
  2113. test_search_trie()
  2114. {
  2115. struct btrie *btrie = btrie_init(NULL);
  2116. const void *data01 = (void *)0xdead0001;
  2117. const void *data11 = (void *)0xdead0101;
  2118. const void *data = (void *)0xdeadbeef;
  2119. unsigned plen, pfx;
  2120. node_t root;
  2121. /* test can follow chain of LC nodes to an exact match */
  2122. init_empty_node(btrie, &root);
  2123. add_to_trie(btrie, &root, 0,
  2124. numbered_bytes, 8 * 2 * LC_BYTES_PER_NODE, data);
  2125. assert(search_trie(&root, 0, numbered_bytes, 8 * 2 * LC_BYTES_PER_NODE)
  2126. == data);
  2127. assert(search_trie(&root, 0, numbered_bytes, 8 * 2 * LC_BYTES_PER_NODE + 1)
  2128. == data);
  2129. assert(search_trie(&root, 0, numbered_bytes, 8 * 2 * LC_BYTES_PER_NODE - 1)
  2130. == NULL);
  2131. assert(search_trie(&root, 0, &numbered_bytes[1], 8 * 2 * LC_BYTES_PER_NODE)
  2132. == NULL);
  2133. /* test can follow extending path to an exact match */
  2134. for (pfx = 0; pfx < (1U << TBM_STRIDE); pfx++) {
  2135. btrie_oct_t prefix0 = pfx << (8 - TBM_STRIDE);
  2136. init_empty_node(btrie, &root);
  2137. tbm_insert_data(btrie, &root.tbm_node, 0, 1, data01);
  2138. tbm_insert_data(btrie, &root.tbm_node, 1, 1, data11);
  2139. add_to_trie(btrie, &root, 0, &prefix0, 8, data);
  2140. assert(search_trie(&root, 0, &prefix0, 8) == data);
  2141. /* test that last matching TBM internal prefix gets picked up */
  2142. if (prefix0 & 0x80)
  2143. assert(search_trie(&root, 0, &prefix0, 7) == data11);
  2144. else
  2145. assert(search_trie(&root, 0, &prefix0, 7) == data01);
  2146. prefix0 ^= 1 << (8 - TBM_STRIDE);
  2147. if (prefix0 & 0x80)
  2148. assert(search_trie(&root, 0, &prefix0, 8) == data11);
  2149. else
  2150. assert(search_trie(&root, 0, &prefix0, 8) == data01);
  2151. }
  2152. /* test finding of TBM internal prefixes */
  2153. init_empty_node(btrie, &root);
  2154. tbm_insert_data(btrie, &root.tbm_node, 0, 1, data01);
  2155. tbm_insert_data(btrie, &root.tbm_node, 1, 1, data11);
  2156. assert(search_trie(&root, 0, numbered_bytes, 0) == NULL);
  2157. for (plen = 1; plen < TBM_STRIDE; plen++) {
  2158. for (pfx = 0; pfx < (1U << TBM_STRIDE); pfx++) {
  2159. btrie_oct_t prefix0 = pfx << (8 - plen);
  2160. if (prefix0 & 0x80)
  2161. assert(search_trie(&root, 0, &prefix0, plen) == data11);
  2162. else
  2163. assert(search_trie(&root, 0, &prefix0, plen) == data01);
  2164. }
  2165. }
  2166. PASS("test_search_trie");
  2167. }
  2168. static int
  2169. unit_tests()
  2170. {
  2171. test_struct_node_packing();
  2172. test_bit();
  2173. test_count_bits();
  2174. test_count_bits_before();
  2175. test_count_bits_from();
  2176. test_extract_bits();
  2177. test_high_bits();
  2178. test_prefixes_equal();
  2179. test_common_prefix();
  2180. test_base_index();
  2181. test_has_internal_data();
  2182. test_init_terminal_node();
  2183. test_coalesce_lc_node();
  2184. test_shorten_lc_node();
  2185. test_split_lc_node();
  2186. test_convert_lc_node_1();
  2187. test_convert_lc_node();
  2188. test_insert_lc_node();
  2189. test_next_pbyte();
  2190. test_init_tbm_node();
  2191. test_add_to_trie();
  2192. test_search_trie();
  2193. puts("\nOK");
  2194. return 0;
  2195. }
  2196. /*****************************************************************
  2197. *
  2198. * btrie_dump: print out the trie structure (for testing)
  2199. *
  2200. */
  2201. #define INDENT_FILL "....:....|....:....|....:....|....:....|"
  2202. static void dump_node(const node_t *node, unsigned pos, btrie_oct_t *prefix,
  2203. int indent);
  2204. static void
  2205. dump_prefix(btrie_oct_t *prefix, unsigned len, int indent, const char *tail)
  2206. {
  2207. unsigned i;
  2208. printf("%*.*s0x", indent, indent, INDENT_FILL);
  2209. for (i = 0; i < len / 8; i++)
  2210. printf("%02x", prefix[i]);
  2211. if (len % 8)
  2212. printf("%02x", prefix[len / 8] & high_bits(len % 8));
  2213. printf("/%u%s", len, tail);
  2214. }
  2215. /* the opposite of extract_bits, sets a short string of bits from integer */
  2216. static void
  2217. insert_bits(btrie_oct_t *prefix, unsigned pos, btrie_oct_t pfx, unsigned nbits)
  2218. {
  2219. if (nbits != 0) {
  2220. unsigned v = (prefix[pos / 8] << 8) + prefix[pos / 8 + 1];
  2221. unsigned mask = (1U << nbits) - 1;
  2222. unsigned shift = 16 - (pos % 8) - nbits;
  2223. v = (v & ~(mask << shift)) | (pfx << shift);
  2224. prefix[pos / 8] = v >> 8;
  2225. prefix[pos / 8 + 1] = (btrie_oct_t)v;
  2226. }
  2227. }
  2228. static void
  2229. dump_tbm_node(const struct tbm_node *node, unsigned pos,
  2230. btrie_oct_t *prefix, int indent)
  2231. {
  2232. unsigned pfx = 0, plen = 0;
  2233. dump_prefix(prefix, pos, indent, " [tbm]\n");
  2234. for (;;) {
  2235. if (plen < TBM_STRIDE) {
  2236. const void **data_p = tbm_data_p(node, pfx, plen);
  2237. if (data_p) {
  2238. insert_bits(prefix, pos, pfx, plen);
  2239. dump_prefix(prefix, pos + plen, indent, "");
  2240. printf(" [%u/%u] (%s)\n", pfx, plen, (const char *)*data_p);
  2241. }
  2242. plen++;
  2243. pfx <<= 1;
  2244. }
  2245. else {
  2246. const node_t *ext_path = tbm_ext_path(node, pfx);
  2247. if (ext_path) {
  2248. insert_bits(prefix, pos, pfx, TBM_STRIDE);
  2249. dump_node(ext_path, pos + TBM_STRIDE, prefix, indent + 1);
  2250. }
  2251. while (pfx & 1) {
  2252. if (--plen == 0)
  2253. return;
  2254. pfx >>= 1;
  2255. }
  2256. pfx++;
  2257. }
  2258. }
  2259. }
  2260. static void
  2261. dump_lc_node(const struct lc_node *node, unsigned pos,
  2262. btrie_oct_t *prefix, int indent)
  2263. {
  2264. unsigned end = pos + lc_len(node);
  2265. btrie_oct_t save_prefix = prefix[lc_shift(pos)];
  2266. memcpy(&prefix[lc_shift(pos)], node->prefix, lc_bytes(node, pos));
  2267. if (lc_is_terminal(node)) {
  2268. dump_prefix(prefix, end, indent, "");
  2269. printf(" (%s)\n", (const char *)node->ptr.data);
  2270. }
  2271. else {
  2272. dump_prefix(prefix, end, indent, "\n");
  2273. dump_node(node->ptr.child, end, prefix, indent + 1);
  2274. }
  2275. prefix[lc_shift(pos)] = save_prefix;
  2276. if (lc_bytes(node, pos) > 1)
  2277. memset(&prefix[lc_shift(pos) + 1], 0, lc_bytes(node, pos) - 1);
  2278. }
  2279. static void
  2280. dump_node(const node_t *node, unsigned pos, btrie_oct_t *prefix, int indent)
  2281. {
  2282. if (is_lc_node(node))
  2283. dump_lc_node(&node->lc_node, pos, prefix, indent);
  2284. else
  2285. dump_tbm_node(&node->tbm_node, pos, prefix, indent);
  2286. }
  2287. static void
  2288. btrie_dump(struct btrie *btrie)
  2289. {
  2290. btrie_oct_t prefix[(BTRIE_MAX_PREFIX + 7) / 8];
  2291. memset(prefix, 0, sizeof(prefix));
  2292. dump_node(&btrie->root, 0, prefix, 0);
  2293. puts(btrie_stats(btrie));
  2294. }
  2295. /****************************************************************
  2296. *
  2297. * test program - just enough to construct a trie and preform a lookup
  2298. *
  2299. */
  2300. #include <arpa/inet.h>
  2301. static int
  2302. parse_prefix(const char *arg, btrie_oct_t prefix[16], unsigned *len)
  2303. {
  2304. char addrbuf[128];
  2305. return sscanf(arg, "%127[0-9a-fA-F:]/%u", addrbuf, len) == 2
  2306. && inet_pton(AF_INET6, addrbuf, prefix) == 1;
  2307. }
  2308. static int
  2309. test_btrie(int argc, char *argv[])
  2310. {
  2311. struct btrie *btrie = btrie_init(NULL);
  2312. int i;
  2313. btrie_oct_t prefix[16];
  2314. unsigned len;
  2315. for (i = 1; i < argc-1; i++) {
  2316. if (!parse_prefix(argv[i], prefix, &len)) {
  2317. fprintf(stderr, "Can not parse arg '%s'\n", argv[i]);
  2318. return 1;
  2319. }
  2320. btrie_add_prefix(btrie, prefix, len, argv[i]);
  2321. }
  2322. btrie_dump(btrie);
  2323. if (argc > 1) {
  2324. const void *data;
  2325. if (!parse_prefix(argv[argc-1], prefix, &len)) {
  2326. fprintf(stderr, "Can not parse arg '%s'\n", argv[argc-1]);
  2327. return 1;
  2328. }
  2329. data = btrie_lookup(btrie, prefix, 128);
  2330. printf("lookup(%s) => %s\n", argv[argc-1], (const char *)data);
  2331. }
  2332. return 0;
  2333. }
  2334. int
  2335. main(int argc, char *argv[])
  2336. {
  2337. if ((pgm_name = strrchr(argv[0], '/')) != NULL)
  2338. pgm_name++;
  2339. else
  2340. pgm_name = argv[0];
  2341. if (argc > 1)
  2342. return test_btrie(argc, argv);
  2343. else
  2344. return unit_tests();
  2345. }
  2346. #endif /* TEST */