]>
Commit | Line | Data |
---|---|---|
718e3744 | 1 | /* |
2 | * Routing Table | |
3 | * Copyright (C) 1998 Kunihiro Ishiguro | |
4 | * | |
5 | * This file is part of GNU Zebra. | |
6 | * | |
7 | * GNU Zebra is free software; you can redistribute it and/or modify it | |
8 | * under the terms of the GNU General Public License as published by the | |
9 | * Free Software Foundation; either version 2, or (at your option) any | |
10 | * later version. | |
11 | * | |
12 | * GNU Zebra is distributed in the hope that it will be useful, but | |
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 | * General Public License for more details. | |
16 | * | |
896014f4 DL |
17 | * You should have received a copy of the GNU General Public License along |
18 | * with this program; see the file COPYING; if not, write to the Free Software | |
19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |
718e3744 | 20 | */ |
21 | ||
22 | #ifndef _ZEBRA_TABLE_H | |
23 | #define _ZEBRA_TABLE_H | |
24 | ||
4a1ab8e4 | 25 | #include "memory.h" |
bc7a2c03 | 26 | #include "hash.h" |
c0c22c2b | 27 | #include "prefix.h" |
66355cf9 | 28 | #include "typesafe.h" |
5e244469 RW |
29 | |
30 | #ifdef __cplusplus | |
31 | extern "C" { | |
32 | #endif | |
33 | ||
0964ad9c | 34 | DECLARE_MTYPE(ROUTE_NODE) |
4a1ab8e4 | 35 | |
f9c1b7bb AS |
36 | /* |
37 | * Forward declarations. | |
38 | */ | |
39 | struct route_node; | |
40 | struct route_table; | |
41 | ||
42 | /* | |
43 | * route_table_delegate_t | |
44 | * | |
45 | * Function vector that can be used by a client to customize the | |
46 | * behavior of one or more route tables. | |
47 | */ | |
2b64873d | 48 | typedef const struct route_table_delegate_t_ route_table_delegate_t; |
f9c1b7bb | 49 | |
d62a17ae | 50 | typedef struct route_node *(*route_table_create_node_func_t)( |
51 | route_table_delegate_t *, struct route_table *); | |
f9c1b7bb | 52 | |
d62a17ae | 53 | typedef void (*route_table_destroy_node_func_t)(route_table_delegate_t *, |
54 | struct route_table *, | |
55 | struct route_node *); | |
f9c1b7bb | 56 | |
d62a17ae | 57 | struct route_table_delegate_t_ { |
58 | route_table_create_node_func_t create_node; | |
59 | route_table_destroy_node_func_t destroy_node; | |
f9c1b7bb AS |
60 | }; |
61 | ||
66355cf9 DS |
62 | PREDECL_HASH(rn_hash_node) |
63 | ||
718e3744 | 64 | /* Routing table top structure. */ |
d62a17ae | 65 | struct route_table { |
66 | struct route_node *top; | |
66355cf9 | 67 | struct rn_hash_node_head hash; |
d62a17ae | 68 | |
69 | /* | |
70 | * Delegate that performs certain functions for this table. | |
71 | */ | |
72 | route_table_delegate_t *delegate; | |
73 | void (*cleanup)(struct route_table *, struct route_node *); | |
74 | ||
75 | unsigned long count; | |
76 | ||
77 | /* | |
78 | * User data. | |
79 | */ | |
80 | void *info; | |
718e3744 | 81 | }; |
82 | ||
4cb260c3 DL |
83 | /* |
84 | * node->link is really internal to the table code and should not be | |
85 | * accessed by outside code. We don't have any writers (yay), though some | |
86 | * readers are left to be fixed. | |
87 | * | |
88 | * rationale: we need to add a hash table in parallel, to speed up | |
89 | * exact-match lookups. | |
90 | * | |
91 | * same really applies for node->parent, though that's less of an issue. | |
92 | * table->link should be - and is - NEVER written by outside code | |
93 | */ | |
94 | #ifdef FRR_COMPILING_TABLE_C | |
95 | #define table_rdonly(x) x | |
96 | #define table_internal(x) x | |
97 | #else | |
98 | #define table_rdonly(x) const x | |
d62a17ae | 99 | #define table_internal(x) \ |
100 | const x __attribute__( \ | |
101 | (deprecated("this should only be accessed by lib/table.c"))) | |
4cb260c3 DL |
102 | /* table_internal is for node->link and node->lock, once we have done |
103 | * something about remaining accesses */ | |
104 | #endif | |
105 | ||
106 | /* so... the problem with this is that "const" doesn't mean "readonly". | |
107 | * It in fact may allow the compiler to optimize based on the assumption | |
108 | * that the value doesn't change. Hence, since the only purpose of this | |
109 | * is to aid in development, don't put the "const" in release builds. | |
110 | * | |
111 | * (I haven't seen this actually break, but GCC and LLVM are getting ever | |
112 | * more aggressive in optimizing...) | |
113 | */ | |
114 | #ifndef DEV_BUILD | |
115 | #undef table_rdonly | |
116 | #define table_rdonly(x) x | |
117 | #endif | |
118 | ||
f9c1b7bb AS |
119 | /* |
120 | * Macro that defines all fields in a route node. | |
121 | */ | |
d62a17ae | 122 | #define ROUTE_NODE_FIELDS \ |
123 | /* Actual prefix of this radix. */ \ | |
124 | struct prefix p; \ | |
125 | \ | |
126 | /* Tree link. */ \ | |
127 | struct route_table *table_rdonly(table); \ | |
128 | struct route_node *table_rdonly(parent); \ | |
129 | struct route_node *table_rdonly(link[2]); \ | |
130 | \ | |
131 | /* Lock of this radix */ \ | |
132 | unsigned int table_rdonly(lock); \ | |
133 | \ | |
66355cf9 | 134 | struct rn_hash_node_item nodehash; \ |
d62a17ae | 135 | /* Each node of route. */ \ |
136 | void *info; \ | |
f9c1b7bb AS |
137 | |
138 | ||
718e3744 | 139 | /* Each routing entry. */ |
d62a17ae | 140 | struct route_node { |
141 | ROUTE_NODE_FIELDS | |
718e3744 | 142 | |
718e3744 | 143 | #define l_left link[0] |
144 | #define l_right link[1] | |
718e3744 | 145 | }; |
146 | ||
28971c8c AS |
147 | typedef struct route_table_iter_t_ route_table_iter_t; |
148 | ||
d62a17ae | 149 | typedef enum { |
150 | RT_ITER_STATE_INIT, | |
151 | RT_ITER_STATE_ITERATING, | |
152 | RT_ITER_STATE_PAUSED, | |
153 | RT_ITER_STATE_DONE | |
28971c8c AS |
154 | } route_table_iter_state_t; |
155 | ||
156 | /* | |
157 | * route_table_iter_t | |
d62a17ae | 158 | * |
28971c8c AS |
159 | * Structure that holds state for iterating over a route table. |
160 | */ | |
d62a17ae | 161 | struct route_table_iter_t_ { |
28971c8c | 162 | |
d62a17ae | 163 | route_table_iter_state_t state; |
28971c8c | 164 | |
d62a17ae | 165 | /* |
166 | * Routing table that we are iterating over. The caller must ensure | |
167 | * that that table outlives the iterator. | |
168 | */ | |
169 | struct route_table *table; | |
28971c8c | 170 | |
d62a17ae | 171 | /* |
172 | * The node that the iterator is currently on. | |
173 | */ | |
174 | struct route_node *current; | |
28971c8c | 175 | |
d62a17ae | 176 | /* |
177 | * The last prefix that the iterator processed before it was paused. | |
178 | */ | |
179 | struct prefix pause_prefix; | |
28971c8c AS |
180 | }; |
181 | ||
718e3744 | 182 | /* Prototypes. */ |
d62a17ae | 183 | extern struct route_table *route_table_init(void); |
f9c1b7bb AS |
184 | |
185 | extern struct route_table * | |
e0700290 | 186 | route_table_init_with_delegate(route_table_delegate_t *delegate); |
d62a17ae | 187 | |
188 | extern route_table_delegate_t *route_table_get_default_delegate(void); | |
189 | ||
6ca30e9e DS |
190 | static inline void *route_table_get_info(struct route_table *table) |
191 | { | |
192 | return table->info; | |
193 | } | |
194 | ||
195 | static inline void route_table_set_info(struct route_table *table, void *d) | |
196 | { | |
197 | table->info = d; | |
198 | } | |
199 | ||
3b18b6c0 DL |
200 | /* ext_pure => extern __attribute__((pure)) |
201 | * does not modify memory (but depends on mem), allows compiler to optimize | |
202 | */ | |
203 | ||
e0700290 | 204 | extern void route_table_finish(struct route_table *table); |
3b18b6c0 DL |
205 | ext_pure struct route_node *route_top(struct route_table *table); |
206 | ext_pure struct route_node *route_next(struct route_node *node); | |
207 | ext_pure struct route_node *route_next_until(struct route_node *node, | |
208 | const struct route_node *limit); | |
209 | extern struct route_node *route_node_get(struct route_table *table, | |
e0700290 | 210 | union prefixconstptr pu); |
3b18b6c0 DL |
211 | ext_pure struct route_node *route_node_lookup(struct route_table *table, |
212 | union prefixconstptr pu); | |
213 | ext_pure struct route_node *route_node_lookup_maynull(struct route_table *table, | |
214 | union prefixconstptr pu); | |
215 | ext_pure struct route_node *route_node_match(struct route_table *table, | |
216 | union prefixconstptr pu); | |
217 | ext_pure struct route_node *route_node_match_ipv4(struct route_table *table, | |
218 | const struct in_addr *addr); | |
219 | ext_pure struct route_node *route_node_match_ipv6(struct route_table *table, | |
220 | const struct in6_addr *addr); | |
221 | ||
222 | ext_pure unsigned long route_table_count(struct route_table *table); | |
e0700290 DS |
223 | |
224 | extern struct route_node *route_node_create(route_table_delegate_t *delegate, | |
225 | struct route_table *table); | |
226 | extern void route_node_delete(struct route_node *node); | |
227 | extern void route_node_destroy(route_table_delegate_t *delegate, | |
228 | struct route_table *table, | |
229 | struct route_node *node); | |
d62a17ae | 230 | |
3b18b6c0 DL |
231 | ext_pure struct route_node *route_table_get_next(struct route_table *table, |
232 | union prefixconstptr pu); | |
233 | ext_pure int route_table_prefix_iter_cmp(const struct prefix *p1, | |
234 | const struct prefix *p2); | |
28971c8c AS |
235 | |
236 | /* | |
237 | * Iterator functions. | |
238 | */ | |
d62a17ae | 239 | extern void route_table_iter_init(route_table_iter_t *iter, |
240 | struct route_table *table); | |
241 | extern void route_table_iter_pause(route_table_iter_t *iter); | |
242 | extern void route_table_iter_cleanup(route_table_iter_t *iter); | |
28971c8c AS |
243 | |
244 | /* | |
245 | * Inline functions. | |
246 | */ | |
247 | ||
01dccc0b JB |
248 | /* Lock node. */ |
249 | static inline struct route_node *route_lock_node(struct route_node *node) | |
250 | { | |
acf3a851 | 251 | (*(unsigned *)&node->lock)++; |
01dccc0b JB |
252 | return node; |
253 | } | |
254 | ||
255 | /* Unlock node. */ | |
0e70e6c8 | 256 | static inline void route_unlock_node(struct route_node *node) |
01dccc0b JB |
257 | { |
258 | assert(node->lock > 0); | |
acf3a851 | 259 | (*(unsigned *)&node->lock)--; |
01dccc0b | 260 | |
0e70e6c8 | 261 | if (node->lock == 0) |
01dccc0b JB |
262 | route_node_delete(node); |
263 | } | |
264 | ||
28971c8c AS |
265 | /* |
266 | * route_table_iter_next | |
267 | * | |
268 | * Get the next node in the tree. | |
269 | */ | |
d62a17ae | 270 | static inline struct route_node *route_table_iter_next(route_table_iter_t *iter) |
28971c8c | 271 | { |
d62a17ae | 272 | struct route_node *node; |
28971c8c | 273 | |
d62a17ae | 274 | switch (iter->state) { |
28971c8c | 275 | |
d62a17ae | 276 | case RT_ITER_STATE_INIT: |
28971c8c | 277 | |
d62a17ae | 278 | /* |
279 | * We're just starting the iteration. | |
280 | */ | |
281 | node = route_top(iter->table); | |
282 | break; | |
28971c8c | 283 | |
d62a17ae | 284 | case RT_ITER_STATE_ITERATING: |
285 | node = route_next(iter->current); | |
286 | break; | |
28971c8c | 287 | |
d62a17ae | 288 | case RT_ITER_STATE_PAUSED: |
28971c8c | 289 | |
d62a17ae | 290 | /* |
291 | * Start with the node following pause_prefix. | |
292 | */ | |
cd2d5852 DL |
293 | node = route_table_get_next(iter->table, &iter->pause_prefix); |
294 | break; | |
28971c8c | 295 | |
d62a17ae | 296 | case RT_ITER_STATE_DONE: |
297 | return NULL; | |
28971c8c | 298 | |
d62a17ae | 299 | default: |
53a39472 QY |
300 | /* Suppress uninitialized variable warning */ |
301 | node = NULL; | |
d62a17ae | 302 | assert(0); |
303 | } | |
28971c8c | 304 | |
d62a17ae | 305 | iter->current = node; |
306 | if (node) | |
307 | iter->state = RT_ITER_STATE_ITERATING; | |
308 | else | |
309 | iter->state = RT_ITER_STATE_DONE; | |
28971c8c | 310 | |
d62a17ae | 311 | return node; |
28971c8c AS |
312 | } |
313 | ||
314 | /* | |
315 | * route_table_iter_is_done | |
316 | * | |
2951a7a4 | 317 | * Returns true if the iteration is complete. |
28971c8c | 318 | */ |
d62a17ae | 319 | static inline int route_table_iter_is_done(route_table_iter_t *iter) |
28971c8c | 320 | { |
d62a17ae | 321 | return iter->state == RT_ITER_STATE_DONE; |
28971c8c AS |
322 | } |
323 | ||
324 | /* | |
325 | * route_table_iter_started | |
326 | * | |
2951a7a4 | 327 | * Returns true if this iterator has started iterating over the tree. |
28971c8c | 328 | */ |
d62a17ae | 329 | static inline int route_table_iter_started(route_table_iter_t *iter) |
28971c8c | 330 | { |
d62a17ae | 331 | return iter->state != RT_ITER_STATE_INIT; |
28971c8c AS |
332 | } |
333 | ||
5e244469 RW |
334 | #ifdef __cplusplus |
335 | } | |
336 | #endif | |
337 | ||
718e3744 | 338 | #endif /* _ZEBRA_TABLE_H */ |