]>
Commit | Line | Data |
---|---|---|
58ef912c MM |
1 | /* |
2 | * BIRD Internet Routing Daemon -- Routing Table | |
3 | * | |
50fe90ed | 4 | * (c) 1998--2000 Martin Mares <mj@ucw.cz> |
58ef912c MM |
5 | * |
6 | * Can be freely distributed and used under the terms of the GNU GPL. | |
7 | */ | |
8 | ||
9 | #ifndef _BIRD_ROUTE_H_ | |
10 | #define _BIRD_ROUTE_H_ | |
11 | ||
0e02abfd | 12 | #include "lib/lists.h" |
5ea39eaa | 13 | #include "lib/bitmap.h" |
1feea03e | 14 | #include "lib/resource.h" |
9b0a0ba9 | 15 | #include "lib/net.h" |
58ef912c | 16 | |
f4a60a9b | 17 | struct ea_list; |
bc10975a | 18 | struct adata; |
2326b001 | 19 | struct protocol; |
4cc78c50 | 20 | struct proto; |
f4a60a9b | 21 | struct rte_src; |
730f2e2c | 22 | struct symbol; |
00b85905 | 23 | struct timer; |
836a87b8 | 24 | struct fib; |
730f2e2c | 25 | struct filter; |
836a87b8 | 26 | struct f_trie; |
9ac16df3 | 27 | struct f_trie_walk_state; |
730f2e2c | 28 | struct cli; |
2326b001 | 29 | |
58ef912c MM |
30 | /* |
31 | * Generic data structure for storing network prefixes. Also used | |
3ab001b9 | 32 | * for the master routing table. Currently implemented as a hash |
62aa008a | 33 | * table. |
58ef912c MM |
34 | * |
35 | * Available operations: | |
36 | * - insertion of new entry | |
37 | * - deletion of entry | |
62aa008a | 38 | * - searching for entry by network prefix |
3ab001b9 | 39 | * - asynchronous retrieval of fib contents |
58ef912c MM |
40 | */ |
41 | ||
42 | struct fib_node { | |
3ab001b9 MM |
43 | struct fib_node *next; /* Next in hash chain */ |
44 | struct fib_iterator *readers; /* List of readers of this node */ | |
fe9f1a6d | 45 | net_addr addr[0]; |
3ab001b9 MM |
46 | }; |
47 | ||
48 | struct fib_iterator { /* See lib/slists.h for an explanation */ | |
49 | struct fib_iterator *prev, *next; /* Must be synced with struct fib_node! */ | |
3ab001b9 MM |
50 | byte efef; /* 0xff to distinguish between iterator and node */ |
51 | byte pad[3]; | |
0ba8a614 | 52 | struct fib_node *node; /* Or NULL if freshly merged */ |
ae80a2de | 53 | uint hash; |
58ef912c MM |
54 | }; |
55 | ||
836a87b8 | 56 | typedef void (*fib_init_fn)(struct fib *, void *); |
ce4aca09 | 57 | |
58ef912c | 58 | struct fib { |
62aa008a MM |
59 | pool *fib_pool; /* Pool holding all our data */ |
60 | slab *fib_slab; /* Slab holding all fib nodes */ | |
61 | struct fib_node **hash_table; /* Node hash table */ | |
ae80a2de PT |
62 | uint hash_size; /* Number of hash table entries (a power of two) */ |
63 | uint hash_order; /* Binary logarithm of hash_size */ | |
04632fd7 | 64 | uint hash_shift; /* 32 - hash_order */ |
fe9f1a6d | 65 | uint addr_type; /* Type of address data stored in fib (NET_*) */ |
f4a60a9b OZ |
66 | uint node_size; /* FIB node size, 0 for nonuniform */ |
67 | uint node_offset; /* Offset of fib_node struct inside of user data */ | |
ae80a2de PT |
68 | uint entries; /* Number of entries */ |
69 | uint entries_min, entries_max; /* Entry count limits (else start rehashing) */ | |
fe9f1a6d | 70 | fib_init_fn init; /* Constructor */ |
58ef912c MM |
71 | }; |
72 | ||
600998fc OZ |
73 | static inline void * fib_node_to_user(struct fib *f, struct fib_node *e) |
74 | { return e ? (void *) ((char *) e - f->node_offset) : NULL; } | |
75 | ||
76 | static inline struct fib_node * fib_user_to_node(struct fib *f, void *e) | |
77 | { return e ? (void *) ((char *) e + f->node_offset) : NULL; } | |
78 | ||
fe9f1a6d | 79 | void fib_init(struct fib *f, pool *p, uint addr_type, uint node_size, uint node_offset, uint hash_order, fib_init_fn init); |
0f7d5b1a | 80 | void *fib_find(struct fib *, const net_addr *); /* Find or return NULL if doesn't exist */ |
0264ccf6 | 81 | void *fib_get_chain(struct fib *f, const net_addr *a); /* Find first node in linked list from hash table */ |
a82f692e | 82 | void *fib_get(struct fib *, const net_addr *); /* Find or create new if nonexistent */ |
0f7d5b1a | 83 | void *fib_route(struct fib *, const net_addr *); /* Longest-match routing lookup */ |
62aa008a | 84 | void fib_delete(struct fib *, void *); /* Remove fib entry */ |
a8b60382 | 85 | void fib_free(struct fib *); /* Destroy the fib */ |
3ab001b9 MM |
86 | void fib_check(struct fib *); /* Consistency check for debugging */ |
87 | ||
88 | void fit_init(struct fib_iterator *, struct fib *); /* Internal functions, don't call */ | |
89 | struct fib_node *fit_get(struct fib *, struct fib_iterator *); | |
90 | void fit_put(struct fib_iterator *, struct fib_node *); | |
8465dccb | 91 | void fit_put_next(struct fib *f, struct fib_iterator *i, struct fib_node *n, uint hpos); |
22c3cf95 OZ |
92 | void fit_put_end(struct fib_iterator *i); |
93 | void fit_copy(struct fib *f, struct fib_iterator *dst, struct fib_iterator *src); | |
8465dccb | 94 | |
600998fc OZ |
95 | |
96 | #define FIB_WALK(fib, type, z) do { \ | |
97 | struct fib_node *fn_, **ff_ = (fib)->hash_table; \ | |
98 | uint count_ = (fib)->hash_size; \ | |
99 | type *z; \ | |
100 | while (count_--) \ | |
101 | for (fn_ = *ff_++; z = fib_node_to_user(fib, fn_); fn_=fn_->next) | |
236d4eb8 MM |
102 | |
103 | #define FIB_WALK_END } while (0) | |
a8b60382 | 104 | |
3ab001b9 MM |
105 | #define FIB_ITERATE_INIT(it, fib) fit_init(it, fib) |
106 | ||
600998fc OZ |
107 | #define FIB_ITERATE_START(fib, it, type, z) do { \ |
108 | struct fib_node *fn_ = fit_get(fib, it); \ | |
109 | uint count_ = (fib)->hash_size; \ | |
110 | uint hpos_ = (it)->hash; \ | |
111 | type *z; \ | |
3ab001b9 | 112 | for(;;) { \ |
600998fc | 113 | if (!fn_) \ |
a82f692e | 114 | { \ |
600998fc | 115 | if (++hpos_ >= count_) \ |
8abbde02 | 116 | break; \ |
600998fc | 117 | fn_ = (fib)->hash_table[hpos_]; \ |
8abbde02 | 118 | continue; \ |
600998fc OZ |
119 | } \ |
120 | z = fib_node_to_user(fib, fn_); | |
3ab001b9 | 121 | |
600998fc | 122 | #define FIB_ITERATE_END fn_ = fn_->next; } } while(0) |
3ab001b9 | 123 | |
600998fc | 124 | #define FIB_ITERATE_PUT(it) fit_put(it, fn_) |
3ab001b9 | 125 | |
600998fc | 126 | #define FIB_ITERATE_PUT_NEXT(it, fib) fit_put_next(fib, it, fn_, hpos_) |
8465dccb | 127 | |
22c3cf95 OZ |
128 | #define FIB_ITERATE_PUT_END(it) fit_put_end(it) |
129 | ||
8465dccb OZ |
130 | #define FIB_ITERATE_UNLINK(it, fib) fit_get(fib, it) |
131 | ||
22c3cf95 OZ |
132 | #define FIB_ITERATE_COPY(dst, src, fib) fit_copy(fib, dst, src) |
133 | ||
8465dccb | 134 | |
58ef912c | 135 | /* |
08e2d625 MM |
136 | * Master Routing Tables. Generally speaking, each of them contains a FIB |
137 | * with each entry pointing to a list of route entries representing routes | |
138 | * to given network (with the selected one at the head). | |
139 | * | |
58ef912c | 140 | * Each of the RTE's contains variable data (the preference and protocol-dependent |
62aa008a | 141 | * metrics) and a pointer to a route attribute block common for many routes). |
08e2d625 MM |
142 | * |
143 | * It's guaranteed that there is at most one RTE for every (prefix,proto) pair. | |
58ef912c MM |
144 | */ |
145 | ||
0e02abfd MM |
146 | struct rtable_config { |
147 | node n; | |
148 | char *name; | |
149 | struct rtable *table; | |
7de45ba4 | 150 | struct proto_config *krt_attached; /* Kernel syncer attached to this table */ |
fe9f1a6d | 151 | uint addr_type; /* Type of address data stored in table (NET_*) */ |
a8a3d95b OZ |
152 | uint gc_threshold; /* Maximum number of operations before GC is run */ |
153 | uint gc_period; /* Approximate time between two consecutive GC runs */ | |
54ddf90f | 154 | u32 debug; /* Debugging flags (D_*) */ |
26822d8f | 155 | byte sorted; /* Routes of network are sorted according to rte_better() */ |
ff397df7 | 156 | byte internal; /* Internal table of a protocol */ |
836a87b8 | 157 | byte trie_used; /* Rtable has attached trie */ |
00b85905 OZ |
158 | btime min_settle_time; /* Minimum settle time for notifications */ |
159 | btime max_settle_time; /* Maximum settle time for notifications */ | |
0e02abfd MM |
160 | }; |
161 | ||
62aa008a | 162 | typedef struct rtable { |
ff397df7 | 163 | resource r; |
0e02abfd | 164 | node n; /* Node in list of all tables */ |
ff397df7 | 165 | pool *rp; /* Resource pool to allocate everything from, including itself */ |
62aa008a | 166 | struct fib fib; |
836a87b8 | 167 | struct f_trie *trie; /* Trie of prefixes defined in fib */ |
62aa008a | 168 | char *name; /* Name of this table */ |
f4a60a9b | 169 | list channels; /* List of attached channels (struct channel) */ |
fe9f1a6d | 170 | uint addr_type; /* Type of address data stored in table (NET_*) */ |
54ddf90f | 171 | u32 debug; /* Debugging flags (D_*) */ |
9c11ec9e | 172 | int pipe_busy; /* Pipe loop detection */ |
50fe90ed | 173 | int use_count; /* Number of protocols using this table */ |
67d8665a | 174 | u32 rt_count; /* Number of routes in the table */ |
3d90241f MM |
175 | |
176 | byte internal; /* Internal table of a protocol */ | |
177 | ||
5ea39eaa | 178 | struct hmap id_map; |
cfe34a31 | 179 | struct hostcache *hostcache; |
b9626ec6 | 180 | struct rtable_config *config; /* Configuration of this table */ |
50fe90ed MM |
181 | struct config *deleted; /* Table doesn't exist in current configuration, |
182 | * delete as soon as use_count becomes 0 and remove | |
183 | * obstacle from this routing table. | |
184 | */ | |
cfe34a31 | 185 | struct event *rt_event; /* Routing table event */ |
a8a3d95b | 186 | struct timer *prune_timer; /* Timer for periodic pruning / GC */ |
00b85905 OZ |
187 | btime last_rt_change; /* Last time when route changed */ |
188 | btime base_settle_time; /* Start time of rtable settling interval */ | |
f047271c | 189 | btime gc_time; /* Time of last GC */ |
a8a3d95b | 190 | uint gc_counter; /* Number of operations since last GC */ |
9135c1f0 | 191 | byte prune_state; /* Table prune state, 1 -> scheduled, 2-> running */ |
de6318f7 | 192 | byte prune_trie; /* Prune prefix trie during next table prune */ |
cfe34a31 OZ |
193 | byte hcu_scheduled; /* Hostcache update is scheduled */ |
194 | byte nhu_state; /* Next Hop Update state */ | |
fb829de6 | 195 | struct fib_iterator prune_fit; /* Rtable prune FIB iterator */ |
cfe34a31 | 196 | struct fib_iterator nhu_fit; /* Next Hop Update FIB iterator */ |
de6318f7 | 197 | struct f_trie *trie_new; /* New prefix trie defined during pruning */ |
5a89edc6 OZ |
198 | struct f_trie *trie_old; /* Old prefix trie waiting to be freed */ |
199 | u32 trie_lock_count; /* Prefix trie locked by walks */ | |
200 | u32 trie_old_lock_count; /* Old prefix trie locked by walks */ | |
00b85905 OZ |
201 | |
202 | list subscribers; /* Subscribers for notifications */ | |
203 | struct timer *settle_timer; /* Settle time for notifications */ | |
1f2eb2ac OZ |
204 | list flowspec_links; /* List of flowspec links, src for NET_IPx and dst for NET_FLOWx */ |
205 | struct f_trie *flowspec_trie; /* Trie for evaluation of flowspec notifications */ | |
333ddd4f | 206 | // struct mpls_domain *mpls_domain; /* Label allocator for MPLS */ |
62aa008a MM |
207 | } rtable; |
208 | ||
00b85905 OZ |
209 | struct rt_subscription { |
210 | node n; | |
211 | rtable *tab; | |
212 | void (*hook)(struct rt_subscription *b); | |
213 | void *data; | |
214 | }; | |
215 | ||
1f2eb2ac OZ |
216 | struct rt_flowspec_link { |
217 | node n; | |
218 | rtable *src; | |
219 | rtable *dst; | |
220 | u32 uc; | |
221 | }; | |
222 | ||
93f50ca3 JMM |
223 | #define NHU_CLEAN 0 |
224 | #define NHU_SCHEDULED 1 | |
225 | #define NHU_RUNNING 2 | |
226 | #define NHU_DIRTY 3 | |
227 | ||
58ef912c | 228 | typedef struct network { |
58ef912c | 229 | struct rte *routes; /* Available routes for this network */ |
fe9f1a6d | 230 | struct fib_node n; /* FIB flags reserved for kernel syncer */ |
58ef912c MM |
231 | } net; |
232 | ||
cfe34a31 | 233 | struct hostcache { |
f2b76f2c OZ |
234 | slab *slab; /* Slab holding all hostentries */ |
235 | struct hostentry **hash_table; /* Hash table for hostentries */ | |
236 | unsigned hash_order, hash_shift; | |
237 | unsigned hash_max, hash_min; | |
238 | unsigned hash_items; | |
c477f489 OZ |
239 | linpool *lp; /* Linpool for trie */ |
240 | struct f_trie *trie; /* Trie of prefixes that might affect hostentries */ | |
241 | list hostentries; /* List of all hostentries */ | |
cfe34a31 OZ |
242 | byte update_hostcache; |
243 | }; | |
244 | ||
245 | struct hostentry { | |
cfe34a31 | 246 | node ln; |
1b180121 OZ |
247 | ip_addr addr; /* IP address of host, part of key */ |
248 | ip_addr link; /* (link-local) IP address of host, used as gw | |
249 | if host is directly attached */ | |
b5e9e519 OZ |
250 | rtable *tab; /* Dependent table, part of key */ |
251 | rtable *owner; /* Nexthop owner table */ | |
f2b76f2c OZ |
252 | struct hostentry *next; /* Next in hash chain */ |
253 | unsigned hash_key; /* Hash key */ | |
cfe34a31 | 254 | unsigned uc; /* Use count */ |
7e95c05d | 255 | struct rta *src; /* Source rta entry */ |
cfe34a31 | 256 | byte dest; /* Chosen route destination type (RTD_...) */ |
039a65d0 | 257 | byte nexthop_linkable; /* Nexthop list is completely non-device */ |
d1e146f2 | 258 | u32 igp_metric; /* Chosen route IGP metric */ |
cfe34a31 OZ |
259 | }; |
260 | ||
58ef912c MM |
261 | typedef struct rte { |
262 | struct rte *next; | |
a0762910 | 263 | net *net; /* Network this RTE belongs to */ |
5cff1d5f | 264 | struct rte_src *src; /* Route source that created the route */ |
f4a60a9b | 265 | struct channel *sender; /* Channel used to send the route to the routing table */ |
1b769b08 | 266 | struct rta *attrs; /* Attributes of this route */ |
5ea39eaa | 267 | u32 id; /* Table specific route id */ |
58ef912c | 268 | byte flags; /* Flags (REF_...) */ |
481f6985 | 269 | byte pflags; /* Protocol-specific flags */ |
f047271c | 270 | btime lastmod; /* Last modified */ |
58ef912c MM |
271 | } rte; |
272 | ||
00a09f3c | 273 | #define REF_COW 1 /* Copy this rte on write */ |
15550957 | 274 | #define REF_FILTERED 2 /* Route is rejected by import filter */ |
0c791f87 OZ |
275 | #define REF_STALE 4 /* Route is stale in a refresh cycle */ |
276 | #define REF_DISCARD 8 /* Route is scheduled for discard */ | |
5bd73431 | 277 | #define REF_MODIFY 16 /* Route is scheduled for modify */ |
cf98be7b OZ |
278 | |
279 | /* Route is valid for propagation (may depend on other flags in the future), accepts NULL */ | |
15550957 | 280 | static inline int rte_is_valid(rte *r) { return r && !(r->flags & REF_FILTERED); } |
cf98be7b | 281 | |
15550957 OZ |
282 | /* Route just has REF_FILTERED flag */ |
283 | static inline int rte_is_filtered(rte *r) { return !!(r->flags & REF_FILTERED); } | |
cf98be7b | 284 | |
e2dc2f30 | 285 | |
23ac9e9a | 286 | /* Types of route announcement, also used as flags */ |
f8aad5d5 | 287 | #define RA_UNDEF 0 /* Undefined RA type */ |
00a09f3c OZ |
288 | #define RA_OPTIMAL 1 /* Announcement of optimal route change */ |
289 | #define RA_ACCEPTED 2 /* Announcement of first accepted route */ | |
290 | #define RA_ANY 3 /* Announcement of any route change */ | |
8d9eef17 | 291 | #define RA_MERGED 4 /* Announcement of optimal route merged with next ones */ |
23ac9e9a | 292 | |
14375237 | 293 | /* Return value of preexport() callback */ |
36da2857 OZ |
294 | #define RIC_ACCEPT 1 /* Accepted by protocol */ |
295 | #define RIC_PROCESS 0 /* Process it through import filter */ | |
296 | #define RIC_REJECT -1 /* Rejected by protocol */ | |
297 | #define RIC_DROP -2 /* Silently dropped by protocol */ | |
298 | ||
863ecfc7 | 299 | extern list routing_tables; |
0e02abfd | 300 | struct config; |
2326b001 MM |
301 | |
302 | void rt_init(void); | |
0e02abfd | 303 | void rt_preconfig(struct config *); |
a8a3d95b | 304 | void rt_postconfig(struct config *); |
50fe90ed MM |
305 | void rt_commit(struct config *new, struct config *old); |
306 | void rt_lock_table(rtable *); | |
307 | void rt_unlock_table(rtable *); | |
5a89edc6 OZ |
308 | struct f_trie * rt_lock_trie(rtable *tab); |
309 | void rt_unlock_trie(rtable *tab, struct f_trie *trie); | |
00b85905 OZ |
310 | void rt_subscribe(rtable *tab, struct rt_subscription *s); |
311 | void rt_unsubscribe(struct rt_subscription *s); | |
1f2eb2ac OZ |
312 | void rt_flowspec_link(rtable *src, rtable *dst); |
313 | void rt_flowspec_unlink(rtable *src, rtable *dst); | |
ff397df7 MM |
314 | rtable *rt_setup(pool *, struct rtable_config *); |
315 | static inline void rt_shutdown(rtable *r) { rfree(r->rp); } | |
316 | ||
0264ccf6 | 317 | static inline net *net_find(rtable *tab, const net_addr *addr) { return (net *) fib_find(&tab->fib, addr); } |
7ee07a3c JMM |
318 | static inline net *net_find_valid(rtable *tab, const net_addr *addr) |
319 | { net *n = net_find(tab, addr); return (n && rte_is_valid(n->routes)) ? n : NULL; } | |
0264ccf6 | 320 | static inline net *net_get(rtable *tab, const net_addr *addr) { return (net *) fib_get(&tab->fib, addr); } |
836a87b8 OZ |
321 | net *net_get(rtable *tab, const net_addr *addr); |
322 | net *net_route(rtable *tab, const net_addr *n); | |
286e2011 | 323 | int net_roa_check(rtable *tab, const net_addr *n, u32 asn); |
bc10975a | 324 | int aspa_check(rtable *tab, const struct adata *path); |
094d2bdb | 325 | rte *rte_find(net *net, struct rte_src *src); |
5cff1d5f | 326 | rte *rte_get_temp(struct rta *, struct rte_src *src); |
65d2a88d | 327 | void rte_update2(struct channel *c, const net_addr *n, rte *new, struct rte_src *src); |
f4a60a9b | 328 | /* rte_update() moved to protocol.h to avoid dependency conflicts */ |
beb5f78a | 329 | int rt_examine(rtable *t, net_addr *a, struct channel *c, const struct filter *filter); |
13c0be19 | 330 | rte *rt_export_merged(struct channel *c, net *net, rte **rt_free, linpool *pool, int silent); |
f4a60a9b OZ |
331 | void rt_refresh_begin(rtable *t, struct channel *c); |
332 | void rt_refresh_end(rtable *t, struct channel *c); | |
5bd73431 | 333 | void rt_modify_stale(rtable *t, struct channel *c); |
f4a60a9b | 334 | void rt_schedule_prune(rtable *t); |
a0762910 | 335 | void rte_dump(rte *); |
04925e90 | 336 | void rte_free(rte *); |
e2dc2f30 MM |
337 | rte *rte_do_cow(rte *); |
338 | static inline rte * rte_cow(rte *r) { return (r->flags & REF_COW) ? rte_do_cow(r) : r; } | |
8d9eef17 | 339 | rte *rte_cow_rta(rte *r, linpool *lp); |
2326b001 | 340 | void rt_dump(rtable *); |
a2ccbb0b | 341 | void rt_dump_all(void); |
f4a60a9b OZ |
342 | int rt_feed_channel(struct channel *c); |
343 | void rt_feed_channel_abort(struct channel *c); | |
682d3f7d OZ |
344 | int rte_update_in(struct channel *c, const net_addr *n, rte *new, struct rte_src *src); |
345 | int rt_reload_channel(struct channel *c); | |
346 | void rt_reload_channel_abort(struct channel *c); | |
347 | void rt_prune_sync(rtable *t, int all); | |
4d48ede5 | 348 | int rte_update_out(struct channel *c, const net_addr *n, rte *new, rte *old0, int refeed); |
fe9f1a6d | 349 | struct rtable_config *rt_new_table(struct symbol *s, uint addr_type); |
2326b001 | 350 | |
977b82fb IP |
351 | int rte_same(rte *x, rte *y); |
352 | ||
fde1cff0 OZ |
353 | static inline int rt_is_ip(rtable *tab) |
354 | { return (tab->addr_type == NET_IP4) || (tab->addr_type == NET_IP6); } | |
355 | ||
356 | static inline int rt_is_vpn(rtable *tab) | |
357 | { return (tab->addr_type == NET_VPN4) || (tab->addr_type == NET_VPN6); } | |
358 | ||
359 | static inline int rt_is_roa(rtable *tab) | |
360 | { return (tab->addr_type == NET_ROA4) || (tab->addr_type == NET_ROA6); } | |
361 | ||
362 | static inline int rt_is_flow(rtable *tab) | |
363 | { return (tab->addr_type == NET_FLOW4) || (tab->addr_type == NET_FLOW6); } | |
364 | ||
682d3f7d | 365 | |
517d05df OZ |
366 | /* Default limit for ECMP next hops, defined in sysdep code */ |
367 | extern const int rt_default_ecmp; | |
0c791f87 | 368 | |
2faf519c JMM |
369 | struct rt_show_data_rtable { |
370 | node n; | |
371 | rtable *table; | |
b2949999 | 372 | struct channel *export_channel; |
2faf519c JMM |
373 | }; |
374 | ||
730f2e2c | 375 | struct rt_show_data { |
04632fd7 | 376 | net_addr *addr; |
b2949999 OZ |
377 | list tables; |
378 | struct rt_show_data_rtable *tab; /* Iterator over table list */ | |
379 | struct rt_show_data_rtable *last_table; /* Last table in output */ | |
380 | struct fib_iterator fit; /* Iterator over networks in table */ | |
9ac16df3 | 381 | struct f_trie_walk_state *walk_state; /* Iterator over networks in trie */ |
5a89edc6 | 382 | struct f_trie *walk_lock; /* Locked trie for walking */ |
2faf519c | 383 | int verbose, tables_defined_by; |
0b39b1cb | 384 | const struct filter *filter; |
4d176e14 | 385 | struct proto *show_protocol; |
ea2ae6dd | 386 | struct proto *export_protocol; |
f4a60a9b | 387 | struct channel *export_channel; |
ce1da96e | 388 | struct config *running_on_config; |
cc75b3e1 | 389 | struct krt_proto *kernel; |
ea97b890 | 390 | int export_mode, addr_mode, primary_only, filtered, stats; |
b2949999 OZ |
391 | |
392 | int table_open; /* Iteration (fit) is open */ | |
9ac16df3 | 393 | int trie_walk; /* Current table is iterated using trie */ |
2faf519c JMM |
394 | int net_counter, rt_counter, show_counter, table_counter; |
395 | int net_counter_last, rt_counter_last, show_counter_last; | |
730f2e2c | 396 | }; |
b2949999 | 397 | |
730f2e2c | 398 | void rt_show(struct rt_show_data *); |
b2949999 | 399 | struct rt_show_data_rtable * rt_show_add_table(struct rt_show_data *d, rtable *t); |
2faf519c JMM |
400 | |
401 | /* Value of table definition mode in struct rt_show_data */ | |
402 | #define RSD_TDB_DEFAULT 0 /* no table specified */ | |
403 | #define RSD_TDB_INDIRECT 0 /* show route ... protocol P ... */ | |
404 | #define RSD_TDB_ALL RSD_TDB_SET /* show route ... table all ... */ | |
405 | #define RSD_TDB_DIRECT RSD_TDB_SET | RSD_TDB_NMN /* show route ... table X table Y ... */ | |
406 | ||
407 | #define RSD_TDB_SET 0x1 /* internal: show empty tables */ | |
408 | #define RSD_TDB_NMN 0x2 /* internal: need matching net */ | |
730f2e2c | 409 | |
ea97b890 OZ |
410 | /* Value of addr_mode */ |
411 | #define RSD_ADDR_EQUAL 1 /* Exact query - show route <addr> */ | |
412 | #define RSD_ADDR_FOR 2 /* Longest prefix match - show route for <addr> */ | |
413 | #define RSD_ADDR_IN 3 /* Interval query - show route in <addr> */ | |
414 | ||
7aa80901 OZ |
415 | /* Value of export_mode in struct rt_show_data */ |
416 | #define RSEM_NONE 0 /* Export mode not used */ | |
417 | #define RSEM_PREEXPORT 1 /* Routes ready for export, before filtering */ | |
418 | #define RSEM_EXPORT 2 /* Routes accepted by export filter */ | |
419 | #define RSEM_NOEXPORT 3 /* Routes rejected by export filter */ | |
5ea39eaa | 420 | #define RSEM_EXPORTED 4 /* Routes marked in export map */ |
7aa80901 | 421 | |
58ef912c MM |
422 | /* |
423 | * Route Attributes | |
424 | * | |
425 | * Beware: All standard BGP attributes must be represented here instead | |
426 | * of making them local to the route. This is needed to ensure proper | |
427 | * construction of BGP route attribute lists. | |
428 | */ | |
429 | ||
4e276a89 JMM |
430 | /* Nexthop structure */ |
431 | struct nexthop { | |
7e95c05d OZ |
432 | ip_addr gw; /* Next hop */ |
433 | struct iface *iface; /* Outgoing interface */ | |
4e276a89 | 434 | struct nexthop *next; |
a1f5e514 | 435 | byte flags; |
e348ef01 | 436 | byte weight; |
039a65d0 JMM |
437 | byte labels_orig; /* Number of labels before hostentry was applied */ |
438 | byte labels; /* Number of all labels */ | |
ec5e5d23 | 439 | u32 label[0]; |
7e95c05d OZ |
440 | }; |
441 | ||
a1f5e514 OZ |
442 | #define RNF_ONLINK 0x1 /* Gateway is onlink regardless of IP ranges */ |
443 | ||
444 | ||
094d2bdb OZ |
445 | struct rte_src { |
446 | struct rte_src *next; /* Hash chain */ | |
447 | struct proto *proto; /* Protocol the source is based on */ | |
21213be5 | 448 | u64 private_id; /* Private ID, assigned by the protocol */ |
094d2bdb OZ |
449 | u32 global_id; /* Globally unique ID of the source */ |
450 | unsigned uc; /* Use count */ | |
451 | }; | |
452 | ||
453 | ||
1b769b08 | 454 | typedef struct rta { |
ee76a92a | 455 | struct rta *next, **pprev; /* Hash chain */ |
9a74622c JMM |
456 | u32 uc; /* Use count */ |
457 | u32 hash_key; /* Hash over important fields */ | |
9a74622c | 458 | struct ea_list *eattrs; /* Extended Attribute chain */ |
9a74622c | 459 | struct hostentry *hostentry; /* Hostentry for recursive next-hops */ |
9a74622c JMM |
460 | ip_addr from; /* Advertising router */ |
461 | u32 igp_metric; /* IGP metric to next hop (for iBGP routes) */ | |
eb937358 MM |
462 | u16 cached:1; /* Are attributes cached? */ |
463 | u16 source:7; /* Route source (RTS_...) */ | |
464 | u16 scope:4; /* Route scope (SCOPE_... -- see ip.h) */ | |
465 | u16 dest:4; /* Route destination type (RTD_...) */ | |
466 | word pref; | |
4e276a89 | 467 | struct nexthop nh; /* Next hop */ |
58ef912c MM |
468 | } rta; |
469 | ||
470 | #define RTS_STATIC 1 /* Normal static route */ | |
471 | #define RTS_INHERIT 2 /* Route inherited from kernel */ | |
472 | #define RTS_DEVICE 3 /* Device route */ | |
473 | #define RTS_STATIC_DEVICE 4 /* Static device route */ | |
474 | #define RTS_REDIRECT 5 /* Learned via redirect */ | |
475 | #define RTS_RIP 6 /* RIP route */ | |
beaf86e1 | 476 | #define RTS_OSPF 7 /* OSPF route */ |
8bf684ec | 477 | #define RTS_OSPF_IA 8 /* OSPF inter-area route */ |
98ac6176 OF |
478 | #define RTS_OSPF_EXT1 9 /* OSPF external route type 1 */ |
479 | #define RTS_OSPF_EXT2 10 /* OSPF external route type 2 */ | |
480 | #define RTS_BGP 11 /* BGP route */ | |
481 | #define RTS_PIPE 12 /* Inter-table wormhole */ | |
937e75d8 | 482 | #define RTS_BABEL 13 /* Babel route */ |
65d2a88d | 483 | #define RTS_RPKI 14 /* Route Origin Authorization */ |
82b74253 | 484 | #define RTS_PERF 15 /* Perf checker */ |
bcff3ae7 OZ |
485 | #define RTS_L3VPN 16 /* MPLS L3VPN */ |
486 | #define RTS_AGGREGATED 17 /* Aggregated route */ | |
487 | #define RTS_MAX 18 | |
58ef912c | 488 | |
62e64905 OZ |
489 | #define RTD_NONE 0 /* Undefined next hop */ |
490 | #define RTD_UNICAST 1 /* Next hop is neighbor router */ | |
58ef912c MM |
491 | #define RTD_BLACKHOLE 2 /* Silently drop packets */ |
492 | #define RTD_UNREACHABLE 3 /* Reject as unreachable */ | |
493 | #define RTD_PROHIBIT 4 /* Administratively prohibited */ | |
665be7f6 | 494 | #define RTD_MAX 5 |
58ef912c | 495 | |
d1e146f2 OZ |
496 | #define IGP_METRIC_UNKNOWN 0x80000000 /* Default igp_metric used when no other |
497 | protocol-specific metric is availabe */ | |
498 | ||
8d9eef17 | 499 | |
4bbc1061 | 500 | extern const char * rta_dest_names[RTD_MAX]; |
665be7f6 OZ |
501 | |
502 | static inline const char *rta_dest_name(uint n) | |
503 | { return (n < RTD_MAX) ? rta_dest_names[n] : "???"; } | |
504 | ||
8d9eef17 OZ |
505 | /* Route has regular, reachable nexthop (i.e. not RTD_UNREACHABLE and like) */ |
506 | static inline int rte_is_reachable(rte *r) | |
62e64905 | 507 | { return r->attrs->dest == RTD_UNICAST; } |
8d9eef17 OZ |
508 | |
509 | ||
58ef912c MM |
510 | /* |
511 | * Extended Route Attributes | |
512 | */ | |
513 | ||
514 | typedef struct eattr { | |
ee7e2ffd | 515 | word id; /* EA_CODE(PROTOCOL_..., protocol-dependent ID) */ |
b77ae37d | 516 | byte flags; /* Protocol-dependent flags */ |
63cf5d5d MM |
517 | byte type:5; /* Attribute type */ |
518 | byte originated:1; /* The attribute has originated locally */ | |
519 | byte fresh:1; /* An uncached attribute (e.g. modified in export filter) */ | |
0f685152 | 520 | byte undef:1; /* Explicitly undefined */ |
58ef912c | 521 | union { |
6e13df70 MM |
522 | uintptr_t data; |
523 | const struct adata *ptr; /* Attribute data elsewhere */ | |
58ef912c MM |
524 | } u; |
525 | } eattr; | |
526 | ||
265419a3 | 527 | |
b77ae37d | 528 | #define EA_CODE(proto,id) (((proto) << 8) | (id)) |
b77ae37d | 529 | #define EA_ID(ea) ((ea) & 0xff) |
265419a3 MM |
530 | #define EA_PROTO(ea) ((ea) >> 8) |
531 | #define EA_CUSTOM(id) ((id) | EA_CUSTOM_BIT) | |
532 | #define EA_IS_CUSTOM(ea) ((ea) & EA_CUSTOM_BIT) | |
533 | #define EA_CUSTOM_ID(ea) ((ea) & ~EA_CUSTOM_BIT) | |
534 | ||
535 | const char *ea_custom_name(uint ea); | |
b77ae37d | 536 | |
333ddd4f OZ |
537 | #define EA_GEN_IGP_METRIC EA_CODE(PROTOCOL_NONE, 0) |
538 | #define EA_MPLS_LABEL EA_CODE(PROTOCOL_NONE, 1) | |
539 | #define EA_MPLS_POLICY EA_CODE(PROTOCOL_NONE, 2) | |
540 | #define EA_MPLS_CLASS EA_CODE(PROTOCOL_NONE, 3) | |
08571b20 | 541 | #define EA_ASPA_PROVIDERS EA_CODE(PROTOCOL_NONE, 4) |
ba5e5940 | 542 | |
8d24b689 | 543 | #define EA_CODE_MASK 0xffff |
265419a3 | 544 | #define EA_CUSTOM_BIT 0x8000 |
8d24b689 | 545 | #define EA_ALLOW_UNDEF 0x10000 /* ea_find: allow EAF_TYPE_UNDEF */ |
315f23a0 | 546 | #define EA_BIT(n) ((n) << 24) /* Used in bitfield accessors */ |
25566c68 | 547 | #define EA_BIT_GET(ea) ((ea) >> 24) |
7d2c7d59 | 548 | #define EA_DATA_ALIGN 4 /* Alignment of adata in attribute cache */ |
8d24b689 | 549 | |
66dbdbd9 | 550 | #define EAF_TYPE_MASK 0x1f /* Mask with this to get type */ |
315f23a0 | 551 | #define EAF_TYPE_INT 0x01 /* 32-bit unsigned integer number */ |
b77ae37d | 552 | #define EAF_TYPE_OPAQUE 0x02 /* Opaque byte string (not filterable) */ |
ca97b489 MM |
553 | #define EAF_TYPE_IP_ADDRESS 0x04 /* IP address */ |
554 | #define EAF_TYPE_ROUTER_ID 0x05 /* Router ID (IPv4 address) */ | |
b475c543 | 555 | #define EAF_TYPE_AS_PATH 0x06 /* BGP AS path (encoding per RFC 1771:4.3) */ |
315f23a0 | 556 | #define EAF_TYPE_BITFIELD 0x09 /* 32-bit embedded bitfield */ |
b475c543 | 557 | #define EAF_TYPE_INT_SET 0x0a /* Set of u32's (e.g., a community list) */ |
42a0c054 | 558 | #define EAF_TYPE_EC_SET 0x0e /* Set of pairs of u32's - ext. community list */ |
66dbdbd9 | 559 | #define EAF_TYPE_LC_SET 0x12 /* Set of triplets of u32's - large community list */ |
224a152c OZ |
560 | #define EAF_TYPE_IFACE 0x14 /* Interface pointer stored in adata */ |
561 | #define EAF_TYPE_STRING 0x16 /* Text string */ | |
b77ae37d | 562 | #define EAF_EMBEDDED 0x01 /* Data stored in eattr.u.data (part of type spec) */ |
ca97b489 | 563 | #define EAF_VAR_LENGTH 0x02 /* Attribute length is variable (part of type spec) */ |
58ef912c | 564 | |
d15b0b0a | 565 | typedef struct adata { |
ae80a2de | 566 | uint length; /* Length of data */ |
58ef912c | 567 | byte data[0]; |
d15b0b0a OZ |
568 | } adata; |
569 | ||
4c553c5a MM |
570 | extern const adata null_adata; /* adata of length 0 */ |
571 | ||
d15b0b0a OZ |
572 | static inline struct adata * |
573 | lp_alloc_adata(struct linpool *pool, uint len) | |
574 | { | |
575 | struct adata *ad = lp_alloc(pool, sizeof(struct adata) + len); | |
576 | ad->length = len; | |
577 | return ad; | |
578 | } | |
58ef912c | 579 | |
4c553c5a | 580 | static inline int adata_same(const struct adata *a, const struct adata *b) |
28a10f84 OZ |
581 | { return (a->length == b->length && !memcmp(a->data, b->data, a->length)); } |
582 | ||
583 | ||
58ef912c MM |
584 | typedef struct ea_list { |
585 | struct ea_list *next; /* In case we have an override list */ | |
b77ae37d | 586 | byte flags; /* Flags: EALF_... */ |
58ef912c | 587 | byte rfu; |
b77ae37d | 588 | word count; /* Number of attributes */ |
58ef912c MM |
589 | eattr attrs[0]; /* Attribute definitions themselves */ |
590 | } ea_list; | |
591 | ||
b77ae37d MM |
592 | #define EALF_SORTED 1 /* Attributes are sorted by code */ |
593 | #define EALF_BISECT 2 /* Use interval bisection for searching */ | |
594 | #define EALF_CACHED 4 /* Attributes belonging to cached rta */ | |
58ef912c | 595 | |
094d2bdb OZ |
596 | struct rte_src *rt_find_source(struct proto *p, u32 id); |
597 | struct rte_src *rt_get_source(struct proto *p, u32 id); | |
598 | static inline void rt_lock_source(struct rte_src *src) { src->uc++; } | |
599 | static inline void rt_unlock_source(struct rte_src *src) { src->uc--; } | |
600 | void rt_prune_sources(void); | |
601 | ||
9fdf9d29 OZ |
602 | struct ea_walk_state { |
603 | ea_list *eattrs; /* Ccurrent ea_list, initially set by caller */ | |
604 | eattr *ea; /* Current eattr, initially NULL */ | |
605 | u32 visited[4]; /* Bitfield, limiting max to 128 */ | |
606 | }; | |
094d2bdb | 607 | |
b77ae37d | 608 | eattr *ea_find(ea_list *, unsigned ea); |
9fdf9d29 | 609 | eattr *ea_walk(struct ea_walk_state *s, uint id, uint max); |
6e13df70 | 610 | uintptr_t ea_get_int(ea_list *, unsigned ea, uintptr_t def); |
b77ae37d MM |
611 | void ea_dump(ea_list *); |
612 | void ea_sort(ea_list *); /* Sort entries in all sub-lists */ | |
6f57dcc0 | 613 | unsigned ea_scan(ea_list *); /* How many bytes do we need for merged ea_list */ |
b77ae37d | 614 | void ea_merge(ea_list *from, ea_list *to); /* Merge sub-lists to allocated buffer */ |
6f57dcc0 | 615 | int ea_same(ea_list *x, ea_list *y); /* Test whether two ea_lists are identical */ |
ae80a2de | 616 | uint ea_hash(ea_list *e); /* Calculate 16-bit hash value */ |
ce1da96e | 617 | ea_list *ea_append(ea_list *to, ea_list *what); |
258be565 | 618 | void ea_format_bitfield(const struct eattr *a, byte *buf, int bufsize, const char **names, int min, int max); |
58ef912c | 619 | |
13c0be19 JMM |
620 | #define ea_normalize(ea) do { \ |
621 | if (ea->next) { \ | |
622 | ea_list *t = alloca(ea_scan(ea)); \ | |
623 | ea_merge(ea, t); \ | |
624 | ea = t; \ | |
625 | } \ | |
626 | ea_sort(ea); \ | |
875cc073 OZ |
627 | if (ea->count == 0) \ |
628 | ea = NULL; \ | |
13c0be19 JMM |
629 | } while(0) \ |
630 | ||
0f685152 MM |
631 | struct ea_one_attr_list { |
632 | ea_list l; | |
633 | eattr a; | |
634 | }; | |
635 | ||
d493d0f1 OZ |
636 | static inline eattr * |
637 | ea_set_attr(ea_list **to, struct linpool *pool, uint id, uint flags, uint type, uintptr_t val) | |
638 | { | |
0f685152 MM |
639 | struct ea_one_attr_list *ea = lp_alloc(pool, sizeof(*ea)); |
640 | *ea = (struct ea_one_attr_list) { | |
641 | .l.flags = EALF_SORTED, | |
642 | .l.count = 1, | |
643 | .l.next = *to, | |
d493d0f1 | 644 | |
0f685152 MM |
645 | .a.id = id, |
646 | .a.type = type, | |
647 | .a.flags = flags, | |
648 | }; | |
d493d0f1 OZ |
649 | |
650 | if (type & EAF_EMBEDDED) | |
0f685152 | 651 | ea->a.u.data = val; |
d493d0f1 | 652 | else |
0f685152 MM |
653 | ea->a.u.ptr = (struct adata *) val; |
654 | ||
655 | *to = &ea->l; | |
d493d0f1 | 656 | |
0f685152 MM |
657 | return &ea->a; |
658 | } | |
659 | ||
660 | static inline void | |
b95dc8f2 | 661 | ea_unset_attr(ea_list **to, struct linpool *pool, bool local, uint code) |
0f685152 MM |
662 | { |
663 | struct ea_one_attr_list *ea = lp_alloc(pool, sizeof(*ea)); | |
664 | *ea = (struct ea_one_attr_list) { | |
665 | .l.flags = EALF_SORTED, | |
666 | .l.count = 1, | |
667 | .l.next = *to, | |
668 | .a.id = code, | |
669 | .a.fresh = local, | |
670 | .a.originated = local, | |
671 | .a.undef = 1, | |
672 | }; | |
673 | ||
674 | *to = &ea->l; | |
d493d0f1 OZ |
675 | } |
676 | ||
677 | static inline void | |
678 | ea_set_attr_u32(ea_list **to, struct linpool *pool, uint id, uint flags, uint type, u32 val) | |
679 | { ea_set_attr(to, pool, id, flags, type, (uintptr_t) val); } | |
680 | ||
681 | static inline void | |
682 | ea_set_attr_ptr(ea_list **to, struct linpool *pool, uint id, uint flags, uint type, struct adata *val) | |
683 | { ea_set_attr(to, pool, id, flags, type, (uintptr_t) val); } | |
684 | ||
685 | static inline void | |
686 | ea_set_attr_data(ea_list **to, struct linpool *pool, uint id, uint flags, uint type, void *data, uint len) | |
687 | { | |
688 | struct adata *a = lp_alloc_adata(pool, len); | |
689 | memcpy(a->data, data, len); | |
690 | ea_set_attr(to, pool, id, flags, type, (uintptr_t) a); | |
691 | } | |
692 | ||
693 | ||
d14f8c3c | 694 | #define NEXTHOP_MAX_SIZE (sizeof(struct nexthop) + sizeof(u32)*MPLS_MAX_LABEL_STACK) |
ec5e5d23 JMM |
695 | |
696 | static inline size_t nexthop_size(const struct nexthop *nh) | |
697 | { return sizeof(struct nexthop) + sizeof(u32)*nh->labels; } | |
4e276a89 JMM |
698 | int nexthop__same(struct nexthop *x, struct nexthop *y); /* Compare multipath nexthops */ |
699 | static inline int nexthop_same(struct nexthop *x, struct nexthop *y) | |
700 | { return (x == y) || nexthop__same(x, y); } | |
f40e2bc2 OZ |
701 | int nexthop_equal_(struct nexthop *x, struct nexthop *y); /* Compare multipath nexthops, ignore labels_orig */ |
702 | static inline int nexthop_equal(struct nexthop *x, struct nexthop *y) | |
703 | { return (x == y) || nexthop_equal_(x, y); } | |
4e276a89 | 704 | struct nexthop *nexthop_merge(struct nexthop *x, struct nexthop *y, int rx, int ry, int max, linpool *lp); |
59d3a361 | 705 | struct nexthop *nexthop_sort(struct nexthop *x); |
333ddd4f | 706 | static inline void nexthop_link(struct rta *a, const struct nexthop *from) |
ec5e5d23 | 707 | { memcpy(&a->nh, from, nexthop_size(from)); } |
62e64905 | 708 | void nexthop_insert(struct nexthop **n, struct nexthop *y); |
4e276a89 | 709 | int nexthop_is_sorted(struct nexthop *x); |
7e95c05d | 710 | |
2326b001 | 711 | void rta_init(void); |
ec5e5d23 | 712 | static inline size_t rta_size(const rta *a) { return sizeof(rta) + sizeof(u32)*a->nh.labels; } |
d14f8c3c | 713 | #define RTA_MAX_SIZE (sizeof(rta) + sizeof(u32)*MPLS_MAX_LABEL_STACK) |
2326b001 | 714 | rta *rta_lookup(rta *); /* Get rta equivalent to this one, uc++ */ |
eb937358 | 715 | static inline int rta_is_cached(rta *r) { return r->cached; } |
2326b001 | 716 | static inline rta *rta_clone(rta *r) { r->uc++; return r; } |
b77ae37d MM |
717 | void rta__free(rta *r); |
718 | static inline void rta_free(rta *r) { if (r && !--r->uc) rta__free(r); } | |
8d9eef17 OZ |
719 | rta *rta_do_cow(rta *o, linpool *lp); |
720 | static inline rta * rta_cow(rta *r, linpool *lp) { return rta_is_cached(r) ? rta_do_cow(r, lp) : r; } | |
2326b001 MM |
721 | void rta_dump(rta *); |
722 | void rta_dump_all(void); | |
13c0be19 | 723 | void rta_show(struct cli *, rta *); |
1e37e35c | 724 | |
09ee846d | 725 | u32 rt_get_igp_metric(rte *rt); |
1e37e35c OZ |
726 | struct hostentry * rt_get_hostentry(rtable *tab, ip_addr a, ip_addr ll, rtable *dep); |
727 | void rta_apply_hostentry(rta *a, struct hostentry *he, mpls_label_stack *mls); | |
728 | ||
729 | static inline void | |
730 | rta_set_recursive_next_hop(rtable *dep, rta *a, rtable *tab, ip_addr gw, ip_addr ll, mpls_label_stack *mls) | |
731 | { | |
732 | rta_apply_hostentry(a, rt_get_hostentry(tab, gw, ll, dep), mls); | |
733 | } | |
cfe34a31 OZ |
734 | |
735 | /* | |
acb04cfd OZ |
736 | * rta_set_recursive_next_hop() acquires hostentry from hostcache and fills |
737 | * rta->hostentry field. New hostentry has zero use count. Cached rta locks its | |
738 | * hostentry (increases its use count), uncached rta does not lock it. Hostentry | |
739 | * with zero use count is removed asynchronously during host cache update, | |
740 | * therefore it is safe to hold such hostentry temorarily. Hostentry holds a | |
741 | * lock for a 'source' rta, mainly to share multipath nexthops. | |
742 | * | |
743 | * There is no need to hold a lock for hostentry->dep table, because that table | |
744 | * contains routes responsible for that hostentry, and therefore is non-empty if | |
745 | * given hostentry has non-zero use count. If the hostentry has zero use count, | |
746 | * the entry is removed before dep is referenced. | |
747 | * | |
748 | * The protocol responsible for routes with recursive next hops should hold a | |
749 | * lock for a 'source' table governing that routes (argument tab to | |
750 | * rta_set_recursive_next_hop()), because its routes reference hostentries | |
751 | * (through rta) related to the governing table. When all such routes are | |
752 | * removed, rtas are immediately removed achieving zero uc. Then the 'source' | |
753 | * table lock could be immediately released, although hostentries may still | |
754 | * exist - they will be freed together with the 'source' table. | |
cfe34a31 OZ |
755 | */ |
756 | ||
757 | static inline void rt_lock_hostentry(struct hostentry *he) { if (he) he->uc++; } | |
758 | static inline void rt_unlock_hostentry(struct hostentry *he) { if (he) he->uc--; } | |
759 | ||
1f2eb2ac OZ |
760 | int rt_flowspec_check(rtable *tab_ip, rtable *tab_flow, const net_addr *n, rta *a, int interior); |
761 | ||
762 | ||
a8b60382 MM |
763 | /* |
764 | * Default protocol preferences | |
765 | */ | |
766 | ||
a82f692e | 767 | #define DEF_PREF_DIRECT 240 /* Directly connected */ |
a8b60382 | 768 | #define DEF_PREF_STATIC 200 /* Static route */ |
916c8c0a | 769 | #define DEF_PREF_OSPF 150 /* OSPF intra-area, inter-area and type 1 external routes */ |
937e75d8 | 770 | #define DEF_PREF_BABEL 130 /* Babel */ |
a8b60382 MM |
771 | #define DEF_PREF_RIP 120 /* RIP */ |
772 | #define DEF_PREF_BGP 100 /* BGP */ | |
65d2a88d | 773 | #define DEF_PREF_RPKI 100 /* RPKI */ |
bcff3ae7 OZ |
774 | #define DEF_PREF_L3VPN_IMPORT 80 /* L3VPN import -> lower than BGP */ |
775 | #define DEF_PREF_L3VPN_EXPORT 120 /* L3VPN export -> higher than BGP */ | |
916c8c0a | 776 | #define DEF_PREF_INHERITED 10 /* Routes inherited from other routing daemons */ |
a8b60382 | 777 | |
af582c48 OZ |
778 | /* |
779 | * Route Origin Authorization | |
780 | */ | |
781 | ||
650b4189 PT |
782 | #define ROA_UNKNOWN 0 |
783 | #define ROA_VALID 1 | |
784 | #define ROA_INVALID 2 | |
af582c48 | 785 | |
bc10975a MM |
786 | #define ASPA_UNKNOWN 0 |
787 | #define ASPA_VALID 1 | |
788 | #define ASPA_INVALID 2 | |
789 | #define ASPA_CONTAINS_CONFED 3 | |
790 | ||
9656dce7 | 791 | #endif |