1 | /*************************************** 2 | $Revision: 1.25 $ 3 | 4 | Radix tree (rx). rxroutines.h - header file for radix tree handling module. 5 | 6 | Status: NOT REVUED, TESTED 7 | 8 | Design and implementation by: marek 9 | 10 | ******************/ /****************** 11 | Copyright (c) 1999 RIPE NCC 12 | 13 | All Rights Reserved 14 | 15 | Permission to use, copy, modify, and distribute this software and its 16 | documentation for any purpose and without fee is hereby granted, 17 | provided that the above copyright notice appear in all copies and that 18 | both that copyright notice and this permission notice appear in 19 | supporting documentation, and that the name of the author not be 20 | used in advertising or publicity pertaining to distribution of the 21 | software without specific, written prior permission. 22 | 23 | THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 24 | ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL 25 | AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY 26 | DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 27 | AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 28 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 29 | ***************************************/ 30 | 31 | #ifndef _RX_H 32 | #define _RX_H 33 | 34 | #include <glib.h> 35 | #ifndef G_THREADS_ENABLED 36 | #error "GLib must be compiled with thread support enabled to be MT-Safe" 37 | #endif 38 | 39 | #include <pthread.h> 40 | #include <stubs.h> 41 | 42 | #include <memwrap.h> 43 | #include <stdio.h> 44 | #include <iproutines.h> 45 | #include <erroutines.h> 46 | 47 | #include "sk.h" /*condat*/ 48 | 49 | #include "thread.h" /*rwlock*/ 50 | 51 | 52 | typedef enum { 53 | RX_FAM_RT = 1, 54 | RX_FAM_IN = 2, 55 | RX_FAM_IP = 4 56 | } rx_fam_t; 57 | 58 | 59 | /*+ the node operation modes +*/ 60 | typedef enum { 61 | RX_OPER_CRE = 1, 62 | RX_OPER_DEL 63 | } rx_oper_mt; 64 | 65 | 66 | /*+ stack building modes +*/ 67 | typedef enum { 68 | RX_STK_CREAT = 1, /*+ - creation = all glue nodes, stop at first non-glue +*/ 69 | RX_STK_QUERY_ALLNOD, /*+ - query = all glue nodes, stop when deep enough */ 70 | RX_STK_QUERY_NOGLUE /*+ - query = no glue nodes, stop when deep enough */ 71 | } rx_stk_mt; 72 | 73 | /*+ the search modes +*/ 74 | typedef enum { 75 | RX_SRCH_CREAT = 1, /*+ special search - does not skip glue nodes +*/ 76 | RX_SRCH_EXLESS, /*+ the default search +*/ 77 | RX_SRCH_EXACT, 78 | RX_SRCH_LESS, 79 | RX_SRCH_MORE, /*+ more specific search +*/ 80 | RX_SRCH_DBLS, /*+ special more spec: return only nodes with 81 | more than one data leaves +*/ 82 | RX_SRCH_RANG /*+ more specific range search, RPSL style : ^n-m +*/ 83 | } rx_srch_mt; 84 | 85 | 86 | #ifdef RX_IMPL_PRINT 87 | char *rx_srch_mode_text[]={ 88 | "", /* begins with 1 */ 89 | "CREAT", 90 | "EXLESS", 91 | "EXACT", 92 | "LESS", 93 | "MORE", 94 | "DBLS", 95 | "RANG" 96 | }; 97 | #endif 98 | 99 | /* constant to mean 'unlimited number of answers from a search' */ 100 | #define RX_ANS_ALL (-1) 101 | 102 | #define RX_ALL_DEPTHS 255 103 | 104 | 105 | /*+ radix tree's memory modes -- not yet implemented +*/ 106 | typedef enum { 107 | RX_MEM_RAMONLY, 108 | RX_MEM_RAMSQL, 109 | RX_MEM_SQLONLY 110 | } rx_mem_mt; 111 | 112 | 113 | 114 | /*+ subtree modes -- not yet implemented +*/ 115 | typedef enum { 116 | RX_SUB_NONE, 117 | RX_SUB_AUTO, 118 | RX_SUB_HAND 119 | } rx_subtree_mt; 120 | 121 | /* modes for tree traversal (walk_tree) */ 122 | typedef enum { 123 | RX_WALK_CNTGLU=1, /*+ default: count also glue nodes and make the level 124 | checking aware of them +*/ 125 | 126 | RX_WALK_SKPGLU=2, /*+ only real nodes counted & watched in level checks +*/ 127 | 128 | RX_WALK_PRFLEN=4, /*+ make level check a check for prefix length; 129 | still only non-glue nodes are counted +*/ 130 | RX_WALK_REVERS=8 /*+ reverse the order of traversing the tree 131 | (first link 1 then 0) +*/ 132 | } rx_walk_mt; 133 | 134 | 135 | /*+ A struct for data hooked via a double linked list at a radix node. 136 | Must uniquely define the object for lookups in the SQL tables and/or memory. 137 | Must also contain enough info to let the delete_node choose (and remove) 138 | the proper object from the (linked) list +*/ 139 | 140 | typedef struct { 141 | ip_range_t iprange; /*+ filled for all trees. Used in rp_search 142 | for determining exact matches (all trees) 143 | and to see if an address is in range 144 | (only IPv4 inetnum trees) +*/ 145 | unsigned char preflen; /* to avoid arithmetics on IPv6 ranges, 146 | we have to store prefix length to 147 | determine the shortest object in search. 148 | This is filled in for all route trees 149 | */ 150 | 151 | char composed; /*+ non-zero for composed inetnums 152 | equal to: the number of prefixes composing 153 | the range - minus 1 +*/ 154 | 155 | void *data_ptr; /*+ to in-memory immediate data +*/ 156 | unsigned data_len; /*+ and its length +*/ 157 | 158 | sql_key_t data_key; /*+ key to the SQL full-text data record +*/ 159 | sql_key_t leaf_key; /*+ pointer to the SQL data leaf record +*/ 160 | } rx_dataleaf_t; 161 | 162 | /*+ 163 | The struct for radix nodes. 164 | 165 | Must contain prefix, parent, left/right child links in memory and sql, 166 | link to the sql version of the node. 167 | And of course data: pointer to a double linked list of rx_data_t's. 168 | +*/ 169 | 170 | typedef struct _rx_node_str { 171 | ip_prefix_t prefix; /*+ who am i. +*/ 172 | 173 | char glue; 174 | /*+ now this is an indicator for a node that it 175 | is not holding a real prefix, 176 | but is only a glue node +*/ 177 | 178 | GList *leaves_ptr; /*+ a double-linked list of rx_data_t structs 179 | the data leaves can be multiple at each node 180 | (due to a user error the inetnum ranges can 181 | overlap, due to multihoming or error routes 182 | can be duplicated ). 183 | So we link a dynamic thing here +*/ 184 | 185 | /* sql_key_t leaves_key; */ 186 | /* "linked list" not needed in sql - 187 | the data leaves can be found in node_leaf 188 | table as those that have 189 | node_key in node_id */ 190 | 191 | struct _rx_node_str 192 | *parent_ptr, /*+ radix links in memory +*/ 193 | *child_ptr[2]; /*+ NULL means empty +*/ 194 | 195 | sql_key_t parent_key, /*+ radix links in SQL +*/ 196 | child_key[2]; /*+ zero means empty +*/ 197 | 198 | sql_key_t node_key; /*+ key of the corresponding SQL radix node +*/ 199 | 200 | } rx_node_t; 201 | 202 | 203 | /*+ 204 | rx_tree_t - defines a radix tree. 205 | 206 | includes a pointer(key) to the top node, 207 | 208 | names of the corresponding SQL tables 209 | (they can be generated automatically, 210 | but this is the place to store the result) 211 | Data_table is for data_key. 212 | Radix_table is for parent_id, right_id, left_id, node_id. 213 | Leaves_table is for leaves_key (double linked list in SQL). 214 | +*/ 215 | 216 | typedef struct _rx_tree_str { 217 | ip_space_t space; /*+ one of IPv4, IPv6 +*/ 218 | rx_fam_t family; /*+ one of RT, IN +*/ 219 | 220 | rx_subtree_mt subtrees; /*+ one of NONE, AUTO, HAND +*/ 221 | rx_mem_mt mem_mode; /*+ where the tree will sit - SQL or RAM +*/ 222 | struct rx_tree_str 223 | *parent_tree; /*+ pointer to the parent tree +*/ 224 | 225 | ip_prefix_t prefix; /*+ of the IP space this tree covers +*/ 226 | 227 | int maxbits; /*+ max depth of this tree 228 | (depends on the space, so it is redundant)+*/ 229 | sql_tblnam_t data_table; 230 | sql_tblnam_t radix_table; 231 | sql_tblnam_t leaves_table; 232 | 233 | int num_nodes; /*+ number of nodes in tree - for assertions +*/ 234 | 235 | rx_node_t *top_ptr; /*+ pointer to the top node +*/ 236 | long top_key; /*+ the same in SQL +*/ 237 | 238 | rw_lock_t rwlock; /*+ per-tree reader/writer lock +*/ 239 | 240 | } rx_tree_t; 241 | 242 | 243 | /*+ this is a definition of a node copy used for: 244 | 245 | * stack elements returned from rx_stack_build, 246 | 247 | * answer elements from an rx_nod_search. 248 | 249 | It *must* hold pointers to the original locations of it (in terms of 250 | memory and SQL) so that one could actually modify the node... 251 | In SQL tree mode it holds also a copy of a node. 252 | This seems to be unnecessary for in-memory radix trees but is a must 253 | for sql ones. 254 | 255 | WARNING!!!!! The fact that pointers to tree and memory / SQL nodes are 256 | here is a subject to race condition. The location of the tree in the 257 | forest list and the node in memory must not change. 258 | 259 | +*/ 260 | 261 | typedef struct { 262 | rx_tree_t *tree; /*+ contains registry_id, space_id, sql table names +*/ 263 | rx_node_t *srcptr; 264 | sql_key_t srckey; 265 | rx_node_t cpy; /*+ filled in if the tree is kept in SQL only mode +*/ 266 | } rx_nodcpy_t; 267 | 268 | 269 | /*+ 270 | This represents one data leaf (by reference). It's used for returning data 271 | from rx_bin_search() to rx_asc_search(). 272 | +*/ 273 | typedef struct { 274 | sql_key_t srckey; 275 | rx_dataleaf_t *leafptr; 276 | } rx_datref_t; 277 | 278 | 279 | /*+ this is a structure used for returning the data from the search. 280 | It contains a copy of the dataleaf and a pointer to the source +*/ 281 | typedef struct { 282 | sql_key_t srckey; 283 | rx_dataleaf_t leafcpy; 284 | } rx_datcpy_t; 285 | 286 | typedef struct { 287 | rx_node_t *node; 288 | int code; 289 | int datatoo; 290 | rx_tree_t *tree; 291 | } rx_treecheck_t; 292 | 293 | /* 294 | * ----------------------------------------------------------------------- 295 | * 296 | * now, THIS is a scrap heap for things that MAY BE useful 297 | */ 298 | 299 | /* a definite pointer to an sql object: table name + key 300 | However, it might be nice to include the table TYPE so that one knows 301 | what data it holds :-) 302 | */ 303 | typedef struct { 304 | sql_tblnam_t name; 305 | sql_key_t key; 306 | } rx_sqlobj_t; 307 | 308 | 309 | typedef struct { 310 | GList **nodlist; 311 | rx_tree_t *tree; 312 | ip_prefix_t *prefix; 313 | } hook_addnode_userdat_t; 314 | 315 | /********************* P R O T O T Y P E S **********************/ 316 | 317 | 318 | void rx_free_list_element(void *cpy, void *trash); 319 | 320 | 321 | 322 | er_ret_t 323 | RX_treecheck( rx_tree_t *tree, int datatoo, rx_treecheck_t *errorfound); 324 | 325 | er_ret_t 326 | RX_tree_cre ( 327 | char *prefixstr, /*+ prefix the tree will cover (string) +*/ 328 | rx_fam_t fam_id, 329 | rx_mem_mt mem_mode, /* memory only, memory+sql, sql only +*/ 330 | rx_subtree_mt subtrees, /*+ one of NONE, AUTO, HAND +*/ 331 | rx_tree_t **treestore /* store the tree pointer here */ 332 | ); 333 | 334 | er_ret_t 335 | RX_bin_search ( 336 | rx_srch_mt search_mode, 337 | int par_a, 338 | int par_b, 339 | rx_tree_t *tree, /* tree ptr */ 340 | ip_prefix_t *prefix, /* binary prefix */ 341 | GList **datleaves, /* data leaves go here */ 342 | int max_count 343 | ); 344 | er_ret_t 345 | rx_bin_node ( 346 | rx_oper_mt mode, /*+ MODE={cre|mod|del} +*/ 347 | ip_prefix_t *newpref, /*+ prefix of the node +*/ 348 | rx_tree_t *tree, /*+ pointer to the tree structure +*/ 349 | rx_dataleaf_t *dataleaf /*+ dataleaf to attach at the node +*/ 350 | ); 351 | er_ret_t 352 | RX_rt_node ( 353 | rx_oper_mt mode, /*+ MODE={cre|mod|del} +*/ 354 | ip_prefix_t *newpref, /*+ prefix of the node +*/ 355 | rx_tree_t *tree, /*+ pointer to the tree structure +*/ 356 | rx_dataleaf_t *dataleaf /*+ dataleaf to attach at the node +*/ 357 | ); 358 | er_ret_t 359 | RX_in_node( rx_oper_mt mode, /*+ MODE={cre|mod|del} +*/ 360 | ip_range_t *rang, /*+ range of IP addresses +*/ 361 | rx_tree_t *tree, /*+ pointer to the tree structure +*/ 362 | rx_dataleaf_t *leafptr /*+ dataleaf to attach at the node +*/ 363 | ); 364 | er_ret_t 365 | rx_build_stack(rx_nodcpy_t stack[], 366 | int *maxdepth, 367 | rx_tree_t *tree, 368 | ip_prefix_t *newpref, 369 | rx_stk_mt dmode 370 | ); 371 | 372 | er_ret_t 373 | rx_nod_search ( 374 | rx_srch_mt search_mode, 375 | int par_a, 376 | int par_b, 377 | /* see rx_asc_search() for explanation */ 378 | rx_tree_t *tree, /* tree ptr */ 379 | ip_prefix_t *prefix, /* binary prefix */ 380 | 381 | rx_nodcpy_t stack[], /* stack==array of node_copies */ 382 | int stackcount, /* number of element on the stack*/ 383 | /* can be set in creat stack */ 384 | 385 | GList **nodlist, /* answers go here */ 386 | int max_count /* max # of answers */ 387 | ); 388 | int 389 | rx_walk_tree(rx_node_t *node, 390 | er_ret_t (*func)(rx_node_t *node, int level, int nodecounter, 391 | void *userptr), 392 | rx_walk_mt walk_mode, 393 | int maxlevel, 394 | int level, 395 | int nodecounter, 396 | void *userptr, 397 | er_ret_t *err); 398 | 399 | 400 | er_ret_t rx_tree_print( sk_conn_st *condat,rx_tree_t *tree ); 401 | void rx_space_list(sk_conn_st *condat); 402 | void rx_nod_print( rx_node_t *node, char *buf, unsigned maxchar ); 403 | void rx_stk_print( rx_nodcpy_t stack[], int stackdepth ); 404 | const char *RX_text_srch_mode(rx_srch_mt mode); 405 | 406 | 407 | /* Function needed to delete radix tree */ 408 | void 409 | rx_delete_treenode(rx_tree_t *tree, rx_node_t *curnode); 410 | 411 | int 412 | rx_delete_tree(rx_tree_t *tree, rx_node_t *node, 413 | int maxlevel, 414 | int level, 415 | int nodecounter, 416 | void *userptr); 417 | 418 | 419 | #undef EXTDEF 420 | #endif /* _RX_H */