1 | /*************************************** 2 | $Revision: 1.18 $ 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 "socket.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 | /* constant to mean 'unlimited number of answers from a search' */ 87 | #define RX_ANS_ALL (-1) 88 | 89 | #define RX_ALL_DEPTHS 255 90 | 91 | 92 | /*+ radix tree's memory modes -- not yet implemented +*/ 93 | typedef enum { 94 | RX_MEM_RAMONLY, 95 | RX_MEM_RAMSQL, 96 | RX_MEM_SQLONLY 97 | } rx_mem_mt; 98 | 99 | 100 | 101 | /*+ subtree modes -- not yet implemented +*/ 102 | typedef enum { 103 | RX_SUB_NONE, 104 | RX_SUB_AUTO, 105 | RX_SUB_HAND 106 | } rx_subtree_mt; 107 | 108 | /* modes for tree traversal (walk_tree) */ 109 | typedef enum { 110 | RX_WALK_CNTGLU=1, /*+ default: count also glue nodes and make the level 111 | checking aware of them +*/ 112 | 113 | RX_WALK_SKPGLU=2, /*+ only real nodes counted & watched in level checks +*/ 114 | 115 | RX_WALK_PRFLEN=4, /*+ make level check a check for prefix length; 116 | still only non-glue nodes are counted +*/ 117 | RX_WALK_REVERS=8 /*+ reverse the order of traversing the tree 118 | (first link 1 then 0) +*/ 119 | } rx_walk_mt; 120 | 121 | 122 | /*+ A struct for data hooked via a double linked list at a radix node. 123 | Must uniquely define the object for lookups in the SQL tables and/or memory. 124 | Must also contain enough info to let the delete_node choose (and remove) 125 | the proper object from the (linked) list +*/ 126 | 127 | typedef struct { 128 | ip_range_t iprange; /*+ for inetnums. empty for routes +*/ 129 | 130 | char composed; /*+ non-zero for composed inetnums 131 | equal to: the number of prefixes composing 132 | the range - minus 1 +*/ 133 | 134 | void *data_ptr; /*+ to in-memory immediate data +*/ 135 | int data_len; /*+ and its length +*/ 136 | 137 | sql_key_t data_key; /*+ key to the SQL full-text data record +*/ 138 | sql_key_t leaf_key; /*+ pointer to the SQL data leaf record +*/ 139 | } rx_dataleaf_t; 140 | 141 | /*+ 142 | The struct for radix nodes. 143 | 144 | Must contain prefix, parent, left/right child links in memory and sql, 145 | link to the sql version of the node. 146 | And of course data: pointer to a double linked list of rx_data_t's. 147 | +*/ 148 | 149 | typedef struct _rx_node_str { 150 | ip_prefix_t prefix; /*+ who am i. +*/ 151 | 152 | char glue; 153 | /*+ now this is an indicator for a node that it 154 | is not holding a real prefix, 155 | but is only a glue node +*/ 156 | 157 | GList *leaves_ptr; /*+ a double-linked list of rx_data_t structs 158 | the data leaves can be multiple at each node 159 | (due to a user error the inetnum ranges can 160 | overlap, due to multihoming or error routes 161 | can be duplicated ). 162 | So we link a dynamic thing here +*/ 163 | 164 | /* sql_key_t leaves_key; */ 165 | /* "linked list" not needed in sql - 166 | the data leaves can be found in node_leaf 167 | table as those that have 168 | node_key in node_id */ 169 | 170 | struct _rx_node_str 171 | *parent_ptr, /*+ radix links in memory +*/ 172 | *child_ptr[2]; /*+ NULL means empty +*/ 173 | 174 | sql_key_t parent_key, /*+ radix links in SQL +*/ 175 | child_key[2]; /*+ zero means empty +*/ 176 | 177 | sql_key_t node_key; /*+ key of the corresponding SQL radix node +*/ 178 | 179 | } rx_node_t; 180 | 181 | 182 | /*+ 183 | rx_tree_t - defines a radix tree. 184 | 185 | includes a pointer(key) to the top node, 186 | 187 | names of the corresponding SQL tables 188 | (they can be generated automatically, 189 | but this is the place to store the result) 190 | Data_table is for data_key. 191 | Radix_table is for parent_id, right_id, left_id, node_id. 192 | Leaves_table is for leaves_key (double linked list in SQL). 193 | +*/ 194 | 195 | typedef struct _rx_tree_str { 196 | ip_space_t space; /*+ one of IPv4, IPv6 +*/ 197 | rx_fam_t family; /*+ one of RT, IN +*/ 198 | 199 | rx_subtree_mt subtrees; /*+ one of NONE, AUTO, HAND +*/ 200 | rx_mem_mt mem_mode; /*+ where the tree will sit - SQL or RAM +*/ 201 | struct rx_tree_str 202 | *parent_tree; /*+ pointer to the parent tree +*/ 203 | 204 | ip_prefix_t prefix; /*+ of the IP space this tree covers +*/ 205 | 206 | int maxbits; /*+ max depth of this tree 207 | (depends on the space, so it is redundant)+*/ 208 | sql_tblnam_t data_table; 209 | sql_tblnam_t radix_table; 210 | sql_tblnam_t leaves_table; 211 | 212 | int num_nodes; /*+ number of nodes in tree - for assertions +*/ 213 | 214 | rx_node_t *top_ptr; /*+ pointer to the top node +*/ 215 | long top_key; /*+ the same in SQL +*/ 216 | 217 | rw_lock_t rwlock; /*+ per-tree reader/writer lock +*/ 218 | 219 | } rx_tree_t; 220 | 221 | 222 | /*+ this is a definition of a node copy used for: 223 | 224 | * stack elements returned from rx_stack_build, 225 | 226 | * answer elements from an rx_nod_search. 227 | 228 | It *must* hold pointers to the original locations of it (in terms of 229 | memory and SQL) so that one could actually modify the node... 230 | In SQL tree mode it holds also a copy of a node. 231 | This seems to be unnecessary for in-memory radix trees but is a must 232 | for sql ones. 233 | 234 | WARNING!!!!! The fact that pointers to tree and memory / SQL nodes are 235 | here is a subject to race condition. The location of the tree in the 236 | forest list and the node in memory must not change. 237 | 238 | +*/ 239 | 240 | typedef struct { 241 | rx_tree_t *tree; /*+ contains registry_id, space_id, sql table names +*/ 242 | rx_node_t *srcptr; 243 | sql_key_t srckey; 244 | rx_node_t cpy; /*+ filled in if the tree is kept in SQL only mode +*/ 245 | } rx_nodcpy_t; 246 | 247 | 248 | /*+ 249 | This represents one data leaf (by reference). It's used for returning data 250 | from rx_bin_search() to rx_asc_search(). 251 | +*/ 252 | typedef struct { 253 | sql_key_t srckey; 254 | rx_dataleaf_t *leafptr; 255 | } rx_datref_t; 256 | 257 | 258 | /*+ this is a structure used for returning the data from the search. 259 | It contains a copy of the dataleaf and a pointer to the source +*/ 260 | typedef struct { 261 | sql_key_t srckey; 262 | rx_dataleaf_t leafcpy; 263 | } rx_datcpy_t; 264 | 265 | 266 | typedef struct { 267 | rx_node_t *node; 268 | int code; 269 | int datatoo; 270 | rx_tree_t *tree; 271 | } rx_treecheck_t; 272 | 273 | /* 274 | * ----------------------------------------------------------------------- 275 | * 276 | * now, THIS is a scrap heap for things that MAY BE useful 277 | */ 278 | 279 | /* a definite pointer to an sql object: table name + key 280 | However, it might be nice to include the table TYPE so that one knows 281 | what data it holds :-) 282 | */ 283 | typedef struct { 284 | sql_tblnam_t name; 285 | sql_key_t key; 286 | } rx_sqlobj_t; 287 | 288 | 289 | typedef struct { 290 | GList **nodlist; 291 | rx_tree_t *tree; 292 | ip_prefix_t *prefix; 293 | } hook_addnode_userdat_t; 294 | 295 | /********************* P R O T O T Y P E S **********************/ 296 | 297 | 298 | void rx_free_list_element(void *cpy, void *trash); 299 | 300 | 301 | 302 | er_ret_t 303 | RX_treecheck( rx_tree_t *tree, int datatoo, rx_treecheck_t *errorfound); 304 | 305 | er_ret_t 306 | RX_tree_cre ( 307 | char *prefixstr, /*+ prefix the tree will cover (string) +*/ 308 | rx_fam_t fam_id, 309 | rx_mem_mt mem_mode, /* memory only, memory+sql, sql only +*/ 310 | rx_subtree_mt subtrees, /*+ one of NONE, AUTO, HAND +*/ 311 | rx_tree_t **treestore /* store the tree pointer here */ 312 | ); 313 | 314 | er_ret_t 315 | RX_bin_search ( 316 | rx_srch_mt search_mode, 317 | int par_a, 318 | int par_b, 319 | rx_tree_t *tree, /* tree ptr */ 320 | ip_prefix_t *prefix, /* binary prefix */ 321 | GList **datleaves, /* data leaves go here */ 322 | int max_count 323 | ); 324 | er_ret_t 325 | RX_bin_node ( 326 | rx_oper_mt mode, /*+ MODE={cre|mod|del} +*/ 327 | ip_prefix_t *newpref, /*+ prefix of the node +*/ 328 | rx_tree_t *tree, /*+ pointer to the tree structure +*/ 329 | rx_dataleaf_t *dataleaf /*+ dataleaf to attach at the node +*/ 330 | ); 331 | er_ret_t 332 | RX_rt_node ( 333 | rx_oper_mt mode, /*+ MODE={cre|mod|del} +*/ 334 | ip_prefix_t *newpref, /*+ prefix of the node +*/ 335 | rx_tree_t *tree, /*+ pointer to the tree structure +*/ 336 | rx_dataleaf_t *dataleaf /*+ dataleaf to attach at the node +*/ 337 | ); 338 | er_ret_t 339 | RX_in_node( rx_oper_mt mode, /*+ MODE={cre|mod|del} +*/ 340 | ip_range_t *rang, /*+ range of IP addresses +*/ 341 | rx_tree_t *tree, /*+ pointer to the tree structure +*/ 342 | rx_dataleaf_t *leafptr /*+ dataleaf to attach at the node +*/ 343 | ); 344 | er_ret_t 345 | rx_build_stack(rx_nodcpy_t stack[], 346 | int *maxdepth, 347 | rx_tree_t *tree, 348 | ip_prefix_t *newpref, 349 | rx_stk_mt dmode 350 | ); 351 | 352 | er_ret_t 353 | rx_nod_search ( 354 | rx_srch_mt search_mode, 355 | int par_a, 356 | int par_b, 357 | /* see rx_asc_search() for explanation */ 358 | rx_tree_t *tree, /* tree ptr */ 359 | ip_prefix_t *prefix, /* binary prefix */ 360 | 361 | rx_nodcpy_t stack[], /* stack==array of node_copies */ 362 | int stackcount, /* number of element on the stack*/ 363 | /* can be set in creat stack */ 364 | 365 | GList **nodlist, /* answers go here */ 366 | int max_count /* max # of answers */ 367 | ); 368 | int 369 | rx_walk_tree(rx_node_t *node, 370 | er_ret_t (*func)(rx_node_t *node, int level, int nodecounter, 371 | void *userptr), 372 | rx_walk_mt walk_mode, 373 | int maxlevel, 374 | int level, 375 | int nodecounter, 376 | void *userptr, 377 | er_ret_t *err); 378 | er_ret_t 379 | rx_preflist_search ( 380 | rx_srch_mt search_mode, 381 | int par_a, 382 | int par_b, 383 | rx_tree_t *mytree, 384 | GList **preflist, 385 | GList **datlist 386 | ); 387 | ip_rangesize_t 388 | rx_find_smallest_span( GList *datlist ); 389 | er_ret_t 390 | rx_asc_append_datref(rx_datref_t *refptr, GList **anslist); 391 | er_ret_t 392 | rx_asc_process_datlist( 393 | rx_srch_mt search_mode, 394 | rx_fam_t fam_id, 395 | GList **datlist, 396 | ip_range_t *testrang, 397 | GList **anslist ); 398 | er_ret_t 399 | rx_asc_make_preflist( 400 | rx_srch_mt search_mode, 401 | char *key, 402 | rx_fam_t fam_id, 403 | GList **preflist, 404 | ip_range_t *testrang, 405 | rx_srch_mt *first_pass_mode 406 | ) ; 407 | 408 | er_ret_t rx_tree_print( sk_conn_st *condat,rx_tree_t *tree ); 409 | void rx_space_list(sk_conn_st *condat); 410 | void rx_nod_print( rx_node_t *node, char *buf, int maxchar ); 411 | void rx_stk_print( rx_nodcpy_t stack[], int stackdepth ); 412 | 413 | #undef EXTDEF 414 | #endif /* _RX_H */