]> git.ipfire.org Git - thirdparty/bird.git/blame - nest/rt-table.c
Fixes missing device attributes when exporting routes to kernel.
[thirdparty/bird.git] / nest / rt-table.c
CommitLineData
62aa008a 1/*
58740ed4 2 * BIRD -- Routing Tables
62aa008a 3 *
50fe90ed 4 * (c) 1998--2000 Martin Mares <mj@ucw.cz>
62aa008a
MM
5 *
6 * Can be freely distributed and used under the terms of the GNU GPL.
7 */
8
58740ed4
MM
9/**
10 * DOC: Routing tables
11 *
12 * Routing tables are probably the most important structures BIRD uses. They
13 * hold all the information about known networks, the associated routes and
14 * their attributes.
15 *
725270cb 16 * There are multiple routing tables (a primary one together with any
58740ed4
MM
17 * number of secondary ones if requested by the configuration). Each table
18 * is basically a FIB containing entries describing the individual
58f7d004 19 * destination networks. For each network (represented by structure &net),
725270cb
MM
20 * there is a one-way linked list of route entries (&rte), the first entry
21 * on the list being the best one (i.e., the one we currently use
58740ed4
MM
22 * for routing), the order of the other ones is undetermined.
23 *
24 * The &rte contains information specific to the route (preference, protocol
25 * metrics, time of last modification etc.) and a pointer to a &rta structure
26 * (see the route attribute module for a precise explanation) holding the
27 * remaining route attributes which are expected to be shared by multiple
28 * routes in order to conserve memory.
29 */
30
6b9fa320 31#undef LOCAL_DEBUG
1a54b1c6 32
62aa008a
MM
33#include "nest/bird.h"
34#include "nest/route.h"
2326b001 35#include "nest/protocol.h"
730f2e2c
MM
36#include "nest/cli.h"
37#include "nest/iface.h"
2326b001 38#include "lib/resource.h"
5996da6a 39#include "lib/event.h"
730f2e2c 40#include "lib/string.h"
0e02abfd 41#include "conf/conf.h"
529c4149 42#include "filter/filter.h"
221135d6 43#include "lib/string.h"
10af3676 44#include "lib/alloca.h"
7d875e09 45
acb60628
OZ
46pool *rt_table_pool;
47
2326b001 48static slab *rte_slab;
e2dc2f30 49static linpool *rte_update_pool;
2326b001 50
0e02abfd 51static list routing_tables;
5996da6a 52
cfd46ee4 53static void rt_format_via(rte *e, byte *via);
cfe34a31
OZ
54static void rt_free_hostcache(rtable *tab);
55static void rt_notify_hostcache(rtable *tab, net *net);
56static void rt_update_hostcache(rtable *tab);
57static void rt_next_hop_update(rtable *tab);
cfe34a31
OZ
58
59static inline void rt_schedule_gc(rtable *tab);
cfd46ee4 60
d1e146f2
OZ
61/* Like fib_route(), but skips empty net entries */
62static net *
63net_route(rtable *tab, ip_addr a, int len)
64{
65 ip_addr a0;
66 net *n;
67
68 while (len >= 0)
69 {
70 a0 = ipa_and(a, ipa_mkmask(len));
71 n = fib_find(&tab->fib, &a0, len);
72 if (n && n->routes)
73 return n;
74 len--;
75 }
76 return NULL;
77}
78
5996da6a 79static void
2326b001
MM
80rte_init(struct fib_node *N)
81{
82 net *n = (net *) N;
83
4c45595e 84 N->flags = 0;
2326b001
MM
85 n->routes = NULL;
86}
87
58740ed4
MM
88/**
89 * rte_find - find a route
90 * @net: network node
91 * @p: protocol
92 *
93 * The rte_find() function returns a route for destination @net
94 * which belongs has been defined by protocol @p.
95 */
2326b001
MM
96rte *
97rte_find(net *net, struct proto *p)
98{
99 rte *e = net->routes;
100
101 while (e && e->attrs->proto != p)
102 e = e->next;
103 return e;
104}
105
58740ed4
MM
106/**
107 * rte_get_temp - get a temporary &rte
3ce8c610 108 * @a: attributes to assign to the new route (a &rta; in case it's
2e9b2421 109 * un-cached, rte_update() will create a cached copy automatically)
58740ed4
MM
110 *
111 * Create a temporary &rte and bind it with the attributes @a.
112 * Also set route preference to the default preference set for
113 * the protocol.
114 */
2326b001
MM
115rte *
116rte_get_temp(rta *a)
117{
118 rte *e = sl_alloc(rte_slab);
119
120 e->attrs = a;
0cdbd397 121 e->flags = 0;
2326b001 122 e->pref = a->proto->preference;
2326b001
MM
123 return e;
124}
125
e2dc2f30
MM
126rte *
127rte_do_cow(rte *r)
128{
129 rte *e = sl_alloc(rte_slab);
130
131 memcpy(e, r, sizeof(rte));
132 e->attrs = rta_clone(r->attrs);
133 e->flags = 0;
134 return e;
135}
136
2326b001
MM
137static int /* Actually better or at least as good as */
138rte_better(rte *new, rte *old)
139{
d9f330c5
MM
140 int (*better)(rte *, rte *);
141
2326b001
MM
142 if (!old)
143 return 1;
144 if (new->pref > old->pref)
145 return 1;
146 if (new->pref < old->pref)
147 return 0;
739ebd8e 148 if (new->attrs->proto->proto != old->attrs->proto->proto)
4c1b4e1a
MM
149 {
150 /*
151 * If the user has configured protocol preferences, so that two different protocols
152 * have the same preference, try to break the tie by comparing addresses. Not too
153 * useful, but keeps the ordering of routes unambiguous.
154 */
155 return new->attrs->proto->proto > old->attrs->proto->proto;
156 }
d9f330c5
MM
157 if (better = new->attrs->proto->rte_better)
158 return better(new, old);
159 return 0;
2326b001
MM
160}
161
cfd46ee4
MM
162static void
163rte_trace(struct proto *p, rte *e, int dir, char *msg)
164{
165 byte via[STD_ADDRESS_P_LENGTH+32];
166
167 rt_format_via(e, via);
168 log(L_TRACE "%s %c %s %I/%d %s", p->name, dir, msg, e->net->n.prefix, e->net->n.pxlen, via);
169}
170
171static inline void
172rte_trace_in(unsigned int flag, struct proto *p, rte *e, char *msg)
173{
174 if (p->debug & flag)
b0a47440 175 rte_trace(p, e, '>', msg);
cfd46ee4
MM
176}
177
178static inline void
179rte_trace_out(unsigned int flag, struct proto *p, rte *e, char *msg)
180{
181 if (p->debug & flag)
b0a47440 182 rte_trace(p, e, '<', msg);
cfd46ee4
MM
183}
184
ebecb6f6
OZ
185/**
186 * do_rte_announce - announce new rte to protocol
187 * @ah: pointer to announce hook
188 * @type: announce type (RA_ANY or RA_OPTIMAL)
189 * @net: pointer to announced network
190 * @new: new rte or NULL
191 * @old: previous rte or NULL
192 * @tmpa: new rte attributes (possibly modified by filter)
193 * @refeed: whether we are refeeding protocol
194 */
529c4149 195static inline void
c0adf7e9 196do_rte_announce(struct announce_hook *ah, int type UNUSED, net *net, rte *new, rte *old, ea_list *tmpa, int refeed)
529c4149 197{
c0adf7e9
OZ
198 struct proto *p = ah->proto;
199 struct filter *filter = ah->out_filter;
200 struct proto_stats *stats = ah->stats;
201
e2dc2f30
MM
202 rte *new0 = new;
203 rte *old0 = old;
08f0290a 204 int ok;
7de45ba4 205
e2dc2f30 206 if (new)
529c4149 207 {
9db74169 208 stats->exp_updates_received++;
925fe2d3 209
13b75bac 210 char *drop_reason = NULL;
ff2857b0 211 if ((ok = p->import_control ? p->import_control(p, &new, &tmpa, rte_update_pool) : 0) < 0)
925fe2d3 212 {
9db74169 213 stats->exp_updates_rejected++;
925fe2d3
OZ
214 drop_reason = "rejected by protocol";
215 }
cfd46ee4
MM
216 else if (ok)
217 rte_trace_out(D_FILTERS, p, new, "forced accept by protocol");
e81b440f
OZ
218 else if ((filter == FILTER_REJECT) ||
219 (filter && f_run(filter, &new, &tmpa, rte_update_pool, FF_FORCE_TMPATTR) > F_ACCEPT))
925fe2d3 220 {
9db74169 221 stats->exp_updates_filtered++;
925fe2d3
OZ
222 drop_reason = "filtered out";
223 }
13b75bac 224 if (drop_reason)
cfd46ee4 225 {
13b75bac 226 rte_trace_out(D_FILTERS, p, new, drop_reason);
2adab6ae
MM
227 if (new != new0)
228 rte_free(new);
cfd46ee4
MM
229 new = NULL;
230 }
529c4149 231 }
925fe2d3 232 else
9db74169 233 stats->exp_withdraws_received++;
925fe2d3 234
11361a10
OZ
235 /*
236 * This is a tricky part - we don't know whether route 'old' was
237 * exported to protocol 'p' or was filtered by the export filter.
238 * We try tu run the export filter to know this to have a correct
cfe34a31 239 * value in 'old' argument of rte_update (and proper filter value)
11361a10
OZ
240 *
241 * FIXME - this is broken because 'configure soft' may change
242 * filters but keep routes. Refeed is expected to be called after
243 * change of the filters and with old == new, therefore we do not
244 * even try to run the filter on an old route, This may lead to
245 * 'spurious withdraws' but ensure that there are no 'missing
246 * withdraws'.
247 *
248 * This is not completely safe as there is a window between
249 * reconfiguration and the end of refeed - if a newly filtered
250 * route disappears during this period, proper withdraw is not
251 * sent (because old would be also filtered) and the route is
252 * not refeeded (because it disappeared before that).
253 */
254
255 if (old && !refeed)
e2dc2f30 256 {
dca75fd7 257 if (filter == FILTER_REJECT)
e2dc2f30
MM
258 old = NULL;
259 else
260 {
261 ea_list *tmpb = p->make_tmp_attrs ? p->make_tmp_attrs(old, rte_update_pool) : NULL;
08f0290a 262 ok = p->import_control ? p->import_control(p, &old, &tmpb, rte_update_pool) : 0;
dca75fd7 263 if (ok < 0 || (!ok && filter && f_run(filter, &old, &tmpb, rte_update_pool, FF_FORCE_TMPATTR) > F_ACCEPT))
13b75bac
MM
264 {
265 if (old != old0)
266 rte_free(old);
267 old = NULL;
268 }
e2dc2f30
MM
269 }
270 }
925fe2d3 271
bf47fe4b 272 /* FIXME - This is broken because of incorrect 'old' value (see above) */
925fe2d3
OZ
273 if (!new && !old)
274 return;
275
276 if (new)
9db74169 277 stats->exp_updates_accepted++;
925fe2d3 278 else
9db74169 279 stats->exp_withdraws_accepted++;
925fe2d3 280
8a7fb885
OZ
281 /* Hack: We do not decrease exp_routes during refeed, we instead
282 reset exp_routes at the start of refeed. */
925fe2d3 283 if (new)
9db74169 284 stats->exp_routes++;
8a7fb885 285 if (old && !refeed)
9db74169 286 stats->exp_routes--;
925fe2d3 287
cfd46ee4
MM
288 if (p->debug & D_ROUTES)
289 {
290 if (new && old)
291 rte_trace_out(D_ROUTES, p, new, "replaced");
292 else if (new)
293 rte_trace_out(D_ROUTES, p, new, "added");
349e21bb 294 else if (old)
cfd46ee4
MM
295 rte_trace_out(D_ROUTES, p, old, "removed");
296 }
08f0290a 297 if (!new)
c0adf7e9 298 p->rt_notify(p, ah->table, net, NULL, old, NULL);
08f0290a
MM
299 else if (tmpa)
300 {
2f711231
MM
301 ea_list *t = tmpa;
302 while (t->next)
303 t = t->next;
304 t->next = new->attrs->eattrs;
c0adf7e9 305 p->rt_notify(p, ah->table, net, new, old, tmpa);
2f711231 306 t->next = NULL;
08f0290a
MM
307 }
308 else
c0adf7e9 309 p->rt_notify(p, ah->table, net, new, old, new->attrs->eattrs);
e2dc2f30
MM
310 if (new && new != new0) /* Discard temporary rte's */
311 rte_free(new);
312 if (old && old != old0)
313 rte_free(old);
529c4149
MM
314}
315
9a8f20fc
MM
316/**
317 * rte_announce - announce a routing table change
318 * @tab: table the route has been added to
23ac9e9a 319 * @type: type of route announcement (RA_OPTIMAL or RA_ANY)
9a8f20fc
MM
320 * @net: network in question
321 * @new: the new route to be announced
23ac9e9a 322 * @old: the previous route for the same network
9a8f20fc
MM
323 * @tmpa: a list of temporary attributes belonging to the new route
324 *
325 * This function gets a routing table update and announces it
f98e2915
OZ
326 * to all protocols that acccepts given type of route announcement
327 * and are connected to the same table by their announcement hooks.
9a8f20fc 328 *
f98e2915
OZ
329 * Route announcement of type RA_OPTIMAL si generated when optimal
330 * route (in routing table @tab) changes. In that case @old stores the
331 * old optimal route.
23ac9e9a 332 *
f98e2915
OZ
333 * Route announcement of type RA_ANY si generated when any route (in
334 * routing table @tab) changes In that case @old stores the old route
335 * from the same protocol.
336 *
337 * For each appropriate protocol, we first call its import_control()
338 * hook which performs basic checks on the route (each protocol has a
339 * right to veto or force accept of the route before any filter is
340 * asked) and adds default values of attributes specific to the new
341 * protocol (metrics, tags etc.). Then it consults the protocol's
342 * export filter and if it accepts the route, the rt_notify() hook of
343 * the protocol gets called.
9a8f20fc 344 */
e2dc2f30 345static void
e81b440f 346rte_announce(rtable *tab, unsigned type, net *net, rte *new, rte *old, ea_list *tmpa)
2326b001 347{
0e02abfd 348 struct announce_hook *a;
2326b001 349
925fe2d3
OZ
350 if (type == RA_OPTIMAL)
351 {
352 if (new)
353 new->attrs->proto->stats.pref_routes++;
354 if (old)
355 old->attrs->proto->stats.pref_routes--;
cfe34a31
OZ
356
357 if (tab->hostcache)
358 rt_notify_hostcache(tab, net);
925fe2d3
OZ
359 }
360
0e02abfd 361 WALK_LIST(a, tab->hooks)
0a2e9d9f 362 {
8c943173 363 ASSERT(a->proto->core_state == FS_HAPPY || a->proto->core_state == FS_FEEDING);
23ac9e9a 364 if (a->proto->accept_ra_types == type)
ff2857b0 365 do_rte_announce(a, type, net, new, old, tmpa, 0);
0a2e9d9f 366 }
2326b001
MM
367}
368
cfe34a31 369
421838ff
MM
370static inline int
371rte_validate(rte *e)
372{
373 int c;
374 net *n = e->net;
375
852b7062 376 if ((n->n.pxlen > BITS_PER_IP_ADDRESS) || !ip_is_prefix(n->n.prefix,n->n.pxlen))
cfd46ee4 377 {
ab164971 378 log(L_WARN "Ignoring bogus prefix %I/%d received via %s",
c0adf7e9 379 n->n.prefix, n->n.pxlen, e->sender->proto->name);
cfd46ee4
MM
380 return 0;
381 }
ff2857b0
OZ
382
383 c = ipa_classify_net(n->n.prefix);
384 if ((c < 0) || !(c & IADDR_HOST) || ((c & IADDR_SCOPE_MASK) <= SCOPE_LINK))
421838ff 385 {
ff2857b0 386 log(L_WARN "Ignoring bogus route %I/%d received via %s",
c0adf7e9 387 n->n.prefix, n->n.pxlen, e->sender->proto->name);
ff2857b0 388 return 0;
421838ff 389 }
ff2857b0 390
421838ff
MM
391 return 1;
392}
393
58740ed4
MM
394/**
395 * rte_free - delete a &rte
396 * @e: &rte to be deleted
397 *
398 * rte_free() deletes the given &rte from the routing table it's linked to.
399 */
04925e90 400void
2326b001 401rte_free(rte *e)
04925e90
MM
402{
403 if (e->attrs->aflags & RTAF_CACHED)
404 rta_free(e->attrs);
405 sl_free(rte_slab, e);
406}
407
408static inline void
409rte_free_quick(rte *e)
2326b001
MM
410{
411 rta_free(e->attrs);
412 sl_free(rte_slab, e);
413}
414
67be5b23
MM
415static int
416rte_same(rte *x, rte *y)
417{
418 return
419 x->attrs == y->attrs &&
420 x->flags == y->flags &&
421 x->pflags == y->pflags &&
422 x->pref == y->pref &&
423 (!x->attrs->proto->rte_same || x->attrs->proto->rte_same(x, y));
424}
425
e2dc2f30 426static void
c0adf7e9 427rte_recalculate(struct announce_hook *ah, net *net, rte *new, ea_list *tmpa, struct proto *src)
2326b001 428{
c0adf7e9
OZ
429 struct proto *p = ah->proto;
430 struct rtable *table = ah->table;
431 struct proto_stats *stats = ah->stats;
2326b001
MM
432 rte *old_best = net->routes;
433 rte *old = NULL;
434 rte **k, *r, *s;
2326b001
MM
435
436 k = &net->routes; /* Find and remove original route from the same protocol */
437 while (old = *k)
438 {
23ac9e9a 439 if (old->attrs->proto == src)
2326b001 440 {
11787b84
OZ
441 /* If there is the same route in the routing table but from
442 * a different sender, then there are two paths from the
443 * source protocol to this routing table through transparent
444 * pipes, which is not allowed.
445 *
446 * We log that and ignore the route. If it is withdraw, we
447 * ignore it completely (there might be 'spurious withdraws',
448 * see FIXME in do_rte_announce())
449 */
c0adf7e9 450 if (old->sender->proto != p)
11787b84
OZ
451 {
452 if (new)
453 {
454 log(L_ERR "Pipe collision detected when sending %I/%d to table %s",
455 net->n.prefix, net->n.pxlen, table->name);
456 rte_free_quick(new);
457 }
458 return;
459 }
460
0b761098 461 if (new && rte_same(old, new))
67be5b23
MM
462 {
463 /* No changes, ignore the new route */
9db74169 464 stats->imp_updates_ignored++;
67be5b23
MM
465 rte_trace_in(D_ROUTES, p, new, "ignored");
466 rte_free_quick(new);
4d9a0d1f
OZ
467#ifdef CONFIG_RIP
468 /* lastmod is used internally by RIP as the last time
469 when the route was received. */
470 if (src->proto == &proto_rip)
471 old->lastmod = now;
472#endif
67be5b23
MM
473 return;
474 }
2326b001
MM
475 *k = old->next;
476 break;
477 }
478 k = &old->next;
479 }
480
925fe2d3
OZ
481 if (!old && !new)
482 {
9db74169 483 stats->imp_withdraws_ignored++;
925fe2d3
OZ
484 return;
485 }
486
ebecb6f6
OZ
487 struct proto_limit *l = ah->in_limit;
488 if (l && !old && new && (stats->imp_routes >= l->limit) && proto_notify_limit(ah, l))
489 {
490 stats->imp_updates_ignored++;
491 rte_trace_in(D_FILTERS, p, new, "ignored [limit]");
492 rte_free_quick(new);
493 return;
494 }
495
925fe2d3 496 if (new)
9db74169 497 stats->imp_updates_accepted++;
925fe2d3 498 else
9db74169 499 stats->imp_withdraws_accepted++;
925fe2d3
OZ
500
501 if (new)
9db74169 502 stats->imp_routes++;
925fe2d3 503 if (old)
9db74169 504 stats->imp_routes--;
925fe2d3 505
23ac9e9a
OZ
506 rte_announce(table, RA_ANY, net, new, old, tmpa);
507
be4cd99a
OZ
508 if (src->rte_recalculate && src->rte_recalculate(table, net, new, old, old_best))
509 goto do_recalculate;
510
c0973621 511 if (new && rte_better(new, old_best))
2326b001 512 {
c0973621
OZ
513 /* The first case - the new route is cleary optimal, we link it
514 at the first position and announce it */
515
85810613 516 rte_trace_in(D_ROUTES, p, new, "added [best]");
23ac9e9a 517 rte_announce(table, RA_OPTIMAL, net, new, old_best, tmpa);
2326b001
MM
518 new->next = net->routes;
519 net->routes = new;
520 }
c0973621 521 else if (old == old_best)
2326b001 522 {
c0973621
OZ
523 /* The second case - the old best route disappeared, we add the
524 new route (if we have any) to the list (we don't care about
525 position) and then we elect the new optimal route and relink
526 that route at the first position and announce it. New optimal
527 route might be NULL if there is no more routes */
528
be4cd99a 529 do_recalculate:
c0973621
OZ
530 /* Add the new route to the list */
531 if (new)
2326b001 532 {
c0973621
OZ
533 rte_trace_in(D_ROUTES, p, new, "added");
534 new->next = net->routes;
535 net->routes = new;
536 }
537
538 /* Find new optimal route */
539 r = NULL;
540 for (s=net->routes; s; s=s->next)
541 if (rte_better(s, r))
542 r = s;
543
544 /* Announce optimal route */
545 rte_announce(table, RA_OPTIMAL, net, r, old_best, tmpa);
546
547 /* And relink it (if there is any) */
548 if (r)
549 {
550 k = &net->routes;
551 while (s = *k)
2326b001 552 {
c0973621 553 if (s == r)
2326b001 554 {
c0973621
OZ
555 *k = r->next;
556 break;
2326b001 557 }
c0973621 558 k = &s->next;
2326b001 559 }
c0973621
OZ
560 r->next = net->routes;
561 net->routes = r;
2326b001 562 }
c0973621
OZ
563 else if (table->gc_counter++ >= table->config->gc_max_ops &&
564 table->gc_time + table->config->gc_min_time <= now)
cfe34a31 565 rt_schedule_gc(table);
c0973621
OZ
566 }
567 else if (new)
568 {
569 /* The third case - the new route is not better than the old
570 best route (therefore old_best != NULL) and the old best
571 route was not removed (therefore old_best == net->routes).
572 We just link the new route after the old best route. */
573
574 ASSERT(net->routes != NULL);
575 new->next = net->routes->next;
576 net->routes->next = new;
577 rte_trace_in(D_ROUTES, p, new, "added");
2326b001 578 }
c0973621 579
e8b29bdc
OZ
580 /* Log the route removal */
581 if (!new && old && (p->debug & D_ROUTES))
582 {
c0973621
OZ
583 if (old != old_best)
584 rte_trace_in(D_ROUTES, p, old, "removed");
585 else if (net->routes)
586 rte_trace_in(D_ROUTES, p, old, "removed [replaced]");
587 else
588 rte_trace_in(D_ROUTES, p, old, "removed [sole]");
589 }
590
2326b001 591 if (old)
5b22683d
MM
592 {
593 if (p->rte_remove)
594 p->rte_remove(net, old);
04925e90 595 rte_free_quick(old);
5b22683d 596 }
8ca8683c
MM
597 if (new)
598 {
599 new->lastmod = now;
600 if (p->rte_insert)
601 p->rte_insert(net, new);
602 }
5b22683d
MM
603}
604
e2dc2f30
MM
605static int rte_update_nest_cnt; /* Nesting counter to allow recursive updates */
606
607static inline void
608rte_update_lock(void)
609{
610 rte_update_nest_cnt++;
611}
612
613static inline void
614rte_update_unlock(void)
615{
616 if (!--rte_update_nest_cnt)
617 lp_flush(rte_update_pool);
618}
619
58740ed4
MM
620/**
621 * rte_update - enter a new update to a routing table
622 * @table: table to be updated
c0adf7e9 623 * @ah: pointer to table announce hook
58740ed4
MM
624 * @net: network node
625 * @p: protocol submitting the update
f98e2915 626 * @src: protocol originating the update
58740ed4
MM
627 * @new: a &rte representing the new route or %NULL for route removal.
628 *
629 * This function is called by the routing protocols whenever they discover
630 * a new route or wish to update/remove an existing route. The right announcement
2e9b2421 631 * sequence is to build route attributes first (either un-cached with @aflags set
58740ed4
MM
632 * to zero or a cached one using rta_lookup(); in this case please note that
633 * you need to increase the use count of the attributes yourself by calling
634 * rta_clone()), call rte_get_temp() to obtain a temporary &rte, fill in all
635 * the appropriate data and finally submit the new &rte by calling rte_update().
636 *
f98e2915
OZ
637 * @src specifies the protocol that originally created the route and the meaning
638 * of protocol-dependent data of @new. If @new is not %NULL, @src have to be the
639 * same value as @new->attrs->proto. @p specifies the protocol that called
640 * rte_update(). In most cases it is the same protocol as @src. rte_update()
641 * stores @p in @new->sender;
642 *
9a8f20fc
MM
643 * When rte_update() gets any route, it automatically validates it (checks,
644 * whether the network and next hop address are valid IP addresses and also
645 * whether a normal routing protocol doesn't try to smuggle a host or link
646 * scope route to the table), converts all protocol dependent attributes stored
647 * in the &rte to temporary extended attributes, consults import filters of the
648 * protocol to see if the route should be accepted and/or its attributes modified,
649 * stores the temporary attributes back to the &rte.
650 *
651 * Now, having a "public" version of the route, we
f98e2915 652 * automatically find any old route defined by the protocol @src
58740ed4
MM
653 * for network @n, replace it by the new one (or removing it if @new is %NULL),
654 * recalculate the optimal route for this destination and finally broadcast
9a8f20fc 655 * the change (if any) to all routing protocols by calling rte_announce().
3ce8c610
MM
656 *
657 * All memory used for attribute lists and other temporary allocations is taken
658 * from a special linear pool @rte_update_pool and freed when rte_update()
659 * finishes.
58740ed4 660 */
23ac9e9a
OZ
661
662void
c0adf7e9 663rte_update2(struct announce_hook *ah, net *net, rte *new, struct proto *src)
e2dc2f30 664{
c0adf7e9
OZ
665 struct proto *p = ah->proto;
666 struct proto_stats *stats = ah->stats;
667 struct filter *filter = ah->in_filter;
e2dc2f30
MM
668 ea_list *tmpa = NULL;
669
670 rte_update_lock();
671 if (new)
672 {
c0adf7e9 673 new->sender = ah;
40b65f94 674
9db74169 675 stats->imp_updates_received++;
cfd46ee4
MM
676 if (!rte_validate(new))
677 {
678 rte_trace_in(D_FILTERS, p, new, "invalid");
9db74169 679 stats->imp_updates_invalid++;
cfd46ee4
MM
680 goto drop;
681 }
40b65f94 682 if (filter == FILTER_REJECT)
cfd46ee4 683 {
9db74169 684 stats->imp_updates_filtered++;
cfd46ee4
MM
685 rte_trace_in(D_FILTERS, p, new, "filtered out");
686 goto drop;
687 }
23ac9e9a
OZ
688 if (src->make_tmp_attrs)
689 tmpa = src->make_tmp_attrs(new, rte_update_pool);
40b65f94 690 if (filter)
e2dc2f30 691 {
ccdc3397 692 ea_list *old_tmpa = tmpa;
40b65f94 693 int fr = f_run(filter, &new, &tmpa, rte_update_pool, 0);
ccdc3397 694 if (fr > F_ACCEPT)
cfd46ee4 695 {
9db74169 696 stats->imp_updates_filtered++;
cfd46ee4
MM
697 rte_trace_in(D_FILTERS, p, new, "filtered out");
698 goto drop;
699 }
23ac9e9a
OZ
700 if (tmpa != old_tmpa && src->store_tmp_attrs)
701 src->store_tmp_attrs(new, tmpa);
e2dc2f30
MM
702 }
703 if (!(new->attrs->aflags & RTAF_CACHED)) /* Need to copy attributes */
704 new->attrs = rta_lookup(new->attrs);
705 new->flags |= REF_COW;
706 }
925fe2d3 707 else
9db74169 708 stats->imp_withdraws_received++;
925fe2d3 709
c0adf7e9 710 rte_recalculate(ah, net, new, tmpa, src);
e2dc2f30
MM
711 rte_update_unlock();
712 return;
713
714drop:
715 rte_free(new);
c0adf7e9 716 rte_recalculate(ah, net, NULL, NULL, src);
e2dc2f30
MM
717 rte_update_unlock();
718}
719
cfe34a31
OZ
720/* Independent call to rte_announce(), used from next hop
721 recalculation, outside of rte_update(). new must be non-NULL */
722static inline void
723rte_announce_i(rtable *tab, unsigned type, net *n, rte *new, rte *old)
724{
725 struct proto *src;
726 ea_list *tmpa;
727
728 rte_update_lock();
729 src = new->attrs->proto;
730 tmpa = src->make_tmp_attrs ? src->make_tmp_attrs(new, rte_update_pool) : NULL;
731 rte_announce(tab, type, n, new, old, tmpa);
732 rte_update_unlock();
733}
734
5b22683d 735void
0e02abfd 736rte_discard(rtable *t, rte *old) /* Non-filtered route deletion, used during garbage collection */
5b22683d 737{
e2dc2f30 738 rte_update_lock();
c0adf7e9 739 rte_recalculate(old->sender, old->net, NULL, NULL, old->attrs->proto);
e2dc2f30 740 rte_update_unlock();
2326b001
MM
741}
742
58740ed4
MM
743/**
744 * rte_dump - dump a route
745 * @e: &rte to be dumped
746 *
747 * This functions dumps contents of a &rte to debug output.
748 */
2326b001 749void
a0762910 750rte_dump(rte *e)
2326b001 751{
a0762910 752 net *n = e->net;
0cdbd397 753 if (n)
e43ae633 754 debug("%-1I/%2d ", n->n.prefix, n->n.pxlen);
a0762910
MM
755 else
756 debug("??? ");
c10421d3 757 debug("KF=%02x PF=%02x pref=%d lm=%d ", n->n.flags, e->pflags, e->pref, now-e->lastmod);
0cdbd397 758 rta_dump(e->attrs);
c10421d3
MM
759 if (e->attrs->proto->proto->dump_attrs)
760 e->attrs->proto->proto->dump_attrs(e);
0cdbd397 761 debug("\n");
2326b001 762}
62aa008a 763
58740ed4
MM
764/**
765 * rt_dump - dump a routing table
766 * @t: routing table to be dumped
767 *
768 * This function dumps contents of a given routing table to debug output.
769 */
2326b001
MM
770void
771rt_dump(rtable *t)
772{
0cdbd397
MM
773 rte *e;
774 net *n;
0e02abfd 775 struct announce_hook *a;
0cdbd397
MM
776
777 debug("Dump of routing table <%s>\n", t->name);
e440395d 778#ifdef DEBUGGING
08e2d625 779 fib_check(&t->fib);
e440395d 780#endif
08e2d625
MM
781 FIB_WALK(&t->fib, fn)
782 {
783 n = (net *) fn;
784 for(e=n->routes; e; e=e->next)
785 rte_dump(e);
0cdbd397 786 }
08e2d625 787 FIB_WALK_END;
0e02abfd
MM
788 WALK_LIST(a, t->hooks)
789 debug("\tAnnounces routes to protocol %s\n", a->proto->name);
0cdbd397 790 debug("\n");
2326b001 791}
62aa008a 792
58740ed4
MM
793/**
794 * rt_dump_all - dump all routing tables
795 *
796 * This function dumps contents of all routing tables to debug output.
797 */
6d45cf21
MM
798void
799rt_dump_all(void)
800{
0e02abfd
MM
801 rtable *t;
802
803 WALK_LIST(t, routing_tables)
804 rt_dump(t);
6d45cf21
MM
805}
806
cfe34a31
OZ
807static inline void
808rt_schedule_gc(rtable *tab)
809{
810 if (tab->gc_scheduled)
811 return;
812
813 tab->gc_scheduled = 1;
814 ev_schedule(tab->rt_event);
815}
816
817static inline void
818rt_schedule_hcu(rtable *tab)
819{
820 if (tab->hcu_scheduled)
821 return;
822
823 tab->hcu_scheduled = 1;
824 ev_schedule(tab->rt_event);
825}
826
827static inline void
828rt_schedule_nhu(rtable *tab)
829{
830 if (tab->nhu_state == 0)
831 ev_schedule(tab->rt_event);
832
833 /* state change 0->1, 2->3 */
834 tab->nhu_state |= 1;
835}
836
fb829de6
OZ
837static void
838rt_prune_nets(rtable *tab)
839{
840 struct fib_iterator fit;
841 int ncnt = 0, ndel = 0;
842
843#ifdef DEBUGGING
844 fib_check(&tab->fib);
845#endif
846
847 FIB_ITERATE_INIT(&fit, &tab->fib);
848again:
849 FIB_ITERATE_START(&tab->fib, &fit, f)
850 {
851 net *n = (net *) f;
852 ncnt++;
853 if (!n->routes) /* Orphaned FIB entry */
854 {
855 FIB_ITERATE_PUT(&fit, f);
856 fib_delete(&tab->fib, f);
857 ndel++;
858 goto again;
859 }
860 }
861 FIB_ITERATE_END(f);
862 DBG("Pruned %d of %d networks\n", ndel, ncnt);
863
864 tab->gc_counter = 0;
865 tab->gc_time = now;
866 tab->gc_scheduled = 0;
867}
868
8f6accb5 869static void
cfe34a31 870rt_event(void *ptr)
5996da6a 871{
cfe34a31
OZ
872 rtable *tab = ptr;
873
874 if (tab->hcu_scheduled)
875 rt_update_hostcache(tab);
0e02abfd 876
cfe34a31
OZ
877 if (tab->nhu_state)
878 rt_next_hop_update(tab);
879
880 if (tab->gc_scheduled)
fb829de6 881 rt_prune_nets(tab);
5996da6a
MM
882}
883
b9626ec6
MM
884void
885rt_setup(pool *p, rtable *t, char *name, struct rtable_config *cf)
886{
887 bzero(t, sizeof(*t));
888 fib_init(&t->fib, p, sizeof(net), 0, rte_init);
889 t->name = name;
890 t->config = cf;
891 init_list(&t->hooks);
892 if (cf)
893 {
cfe34a31
OZ
894 t->rt_event = ev_new(p);
895 t->rt_event->hook = rt_event;
896 t->rt_event->data = t;
2eca3b3a 897 t->gc_time = now;
b9626ec6
MM
898 }
899}
900
58740ed4
MM
901/**
902 * rt_init - initialize routing tables
903 *
904 * This function is called during BIRD startup. It initializes the
905 * routing table module.
906 */
2326b001
MM
907void
908rt_init(void)
909{
910 rta_init();
5996da6a 911 rt_table_pool = rp_new(&root_pool, "Routing tables");
e2dc2f30 912 rte_update_pool = lp_new(rt_table_pool, 4080);
5996da6a 913 rte_slab = sl_new(rt_table_pool, sizeof(rte));
0e02abfd 914 init_list(&routing_tables);
2326b001 915}
1a54b1c6 916
fb829de6
OZ
917
918/* Called from proto_schedule_flush_loop() only,
919 ensuring that all prune states are zero */
920void
921rt_schedule_prune_all(void)
1a54b1c6 922{
fb829de6
OZ
923 rtable *t;
924
925 WALK_LIST(t, routing_tables)
926 t->prune_state = 1;
927}
928
929static inline int
930rt_prune_step(rtable *tab, int *max_feed)
931{
932 struct fib_iterator *fit = &tab->prune_fit;
1a54b1c6
MM
933
934 DBG("Pruning route table %s\n", tab->name);
0521e4f6
MM
935#ifdef DEBUGGING
936 fib_check(&tab->fib);
937#endif
fb829de6
OZ
938
939 if (tab->prune_state == 0)
940 return 1;
941
942 if (tab->prune_state == 1)
943 {
944 FIB_ITERATE_INIT(fit, &tab->fib);
945 tab->prune_state = 2;
946 }
947
08e2d625 948again:
fb829de6 949 FIB_ITERATE_START(&tab->fib, fit, fn)
1a54b1c6 950 {
fb829de6 951 net *n = (net *) fn;
08e2d625 952 rte *e;
fb829de6 953
08e2d625 954 rescan:
fb829de6 955 for (e=n->routes; e; e=e->next)
c0adf7e9
OZ
956 if (e->sender->proto->core_state != FS_HAPPY &&
957 e->sender->proto->core_state != FS_FEEDING)
08e2d625 958 {
fb829de6
OZ
959 if (*max_feed <= 0)
960 {
961 FIB_ITERATE_PUT(fit, fn);
962 return 0;
963 }
964
0e02abfd 965 rte_discard(tab, e);
fb829de6
OZ
966 (*max_feed)--;
967
08e2d625
MM
968 goto rescan;
969 }
fb829de6 970 if (!n->routes) /* Orphaned FIB entry */
1a54b1c6 971 {
fb829de6
OZ
972 FIB_ITERATE_PUT(fit, fn);
973 fib_delete(&tab->fib, fn);
08e2d625 974 goto again;
1a54b1c6 975 }
1a54b1c6 976 }
fb829de6
OZ
977 FIB_ITERATE_END(fn);
978
0521e4f6
MM
979#ifdef DEBUGGING
980 fib_check(&tab->fib);
981#endif
fb829de6
OZ
982
983 tab->prune_state = 0;
984 return 1;
1a54b1c6 985}
0e02abfd 986
58740ed4 987/**
fb829de6
OZ
988 * rt_prune_loop - prune routing tables
989 * @tab: routing table to be pruned
58740ed4 990 *
fb829de6
OZ
991 * The prune loop scans routing tables and removes routes belonging to
992 * inactive protocols and also stale network entries. Returns 1 when
993 * all such routes are pruned. It is a part of the protocol flushing
994 * loop.
58740ed4 995 */
fb829de6
OZ
996int
997rt_prune_loop(void)
0e02abfd
MM
998{
999 rtable *t;
fb829de6 1000 int max_feed = 512;
0e02abfd
MM
1001
1002 WALK_LIST(t, routing_tables)
fb829de6
OZ
1003 if (! rt_prune_step(t, &max_feed))
1004 return 0;
1005
1006 return 1;
0e02abfd
MM
1007}
1008
cfe34a31
OZ
1009void
1010rt_preconfig(struct config *c)
1011{
1012 struct symbol *s = cf_find_symbol("master");
1013
1014 init_list(&c->tables);
1015 c->master_rtc = rt_new_table(s);
1016}
1017
1018
1019/*
1020 * Some functions for handing internal next hop updates
1021 * triggered by rt_schedule_nhu().
1022 */
1023
cfe34a31
OZ
1024static inline int
1025rta_next_hop_outdated(rta *a)
1026{
1027 struct hostentry *he = a->hostentry;
7e95c05d
OZ
1028
1029 if (!he)
1030 return 0;
1031
1032 if (!he->src)
1033 return a->dest != RTD_UNREACHABLE;
1034
1035 return (a->iface != he->src->iface) || !ipa_equal(a->gw, he->gw) ||
1036 (a->dest != he->dest) || (a->igp_metric != he->igp_metric) ||
1037 !mpnh_same(a->nexthops, he->src->nexthops);
cfe34a31
OZ
1038}
1039
1040static inline void
1041rta_apply_hostentry(rta *a, struct hostentry *he)
1042{
1043 a->hostentry = he;
7e95c05d 1044 a->iface = he->src ? he->src->iface : NULL;
cfe34a31
OZ
1045 a->gw = he->gw;
1046 a->dest = he->dest;
d1e146f2 1047 a->igp_metric = he->igp_metric;
7e95c05d 1048 a->nexthops = he->src ? he->src->nexthops : NULL;
cfe34a31
OZ
1049}
1050
1051static inline rte *
1052rt_next_hop_update_rte(rtable *tab, rte *old)
1053{
1054 rta a;
1055 memcpy(&a, old->attrs, sizeof(rta));
1056 rta_apply_hostentry(&a, old->attrs->hostentry);
1057 a.aflags = 0;
1058
1059 rte *e = sl_alloc(rte_slab);
1060 memcpy(e, old, sizeof(rte));
1061 e->attrs = rta_lookup(&a);
1062
1063 return e;
1064}
1065
1066static inline int
1067rt_next_hop_update_net(rtable *tab, net *n)
1068{
1069 rte **k, *e, *new, *old_best, **new_best;
1070 int count = 0;
1071 int free_old_best = 0;
1072
1073 old_best = n->routes;
1074 if (!old_best)
1075 return 0;
1076
cfe34a31 1077 for (k = &n->routes; e = *k; k = &e->next)
be4cd99a
OZ
1078 if (rta_next_hop_outdated(e->attrs))
1079 {
1080 new = rt_next_hop_update_rte(tab, e);
1081 *k = new;
cfe34a31 1082
be4cd99a 1083 rte_announce_i(tab, RA_ANY, n, new, e);
c0adf7e9 1084 rte_trace_in(D_ROUTES, new->sender->proto, new, "updated");
cfe34a31 1085
be4cd99a
OZ
1086 /* Call a pre-comparison hook */
1087 /* Not really an efficient way to compute this */
1088 if (e->attrs->proto->rte_recalculate)
1089 e->attrs->proto->rte_recalculate(tab, n, new, e, NULL);
cfe34a31 1090
be4cd99a
OZ
1091 if (e != old_best)
1092 rte_free_quick(e);
1093 else /* Freeing of the old best rte is postponed */
1094 free_old_best = 1;
cfe34a31 1095
be4cd99a
OZ
1096 e = new;
1097 count++;
1098 }
1099
1100 if (!count)
1101 return 0;
1102
1103 /* Find the new best route */
1104 new_best = NULL;
1105 for (k = &n->routes; e = *k; k = &e->next)
1106 {
cfe34a31
OZ
1107 if (!new_best || rte_better(e, *new_best))
1108 new_best = k;
1109 }
1110
1111 /* Relink the new best route to the first position */
1112 new = *new_best;
1113 if (new != n->routes)
1114 {
1115 *new_best = new->next;
1116 new->next = n->routes;
1117 n->routes = new;
1118 }
1119
1120 /* Announce the new best route */
1121 if (new != old_best)
1122 {
1123 rte_announce_i(tab, RA_OPTIMAL, n, new, old_best);
c0adf7e9 1124 rte_trace_in(D_ROUTES, new->sender->proto, new, "updated [best]");
cfe34a31
OZ
1125 }
1126
1127 if (free_old_best)
1128 rte_free_quick(old_best);
1129
1130 return count;
1131}
1132
1133static void
1134rt_next_hop_update(rtable *tab)
1135{
1136 struct fib_iterator *fit = &tab->nhu_fit;
1137 int max_feed = 32;
1138
1139 if (tab->nhu_state == 0)
1140 return;
1141
1142 if (tab->nhu_state == 1)
1143 {
1144 FIB_ITERATE_INIT(fit, &tab->fib);
1145 tab->nhu_state = 2;
1146 }
1147
1148 FIB_ITERATE_START(&tab->fib, fit, fn)
1149 {
1150 if (max_feed <= 0)
1151 {
1152 FIB_ITERATE_PUT(fit, fn);
1153 ev_schedule(tab->rt_event);
1154 return;
1155 }
1156 max_feed -= rt_next_hop_update_net(tab, (net *) fn);
1157 }
1158 FIB_ITERATE_END(fn);
1159
1160 /* state change 2->0, 3->1 */
1161 tab->nhu_state &= 1;
1162
1163 if (tab->nhu_state > 0)
1164 ev_schedule(tab->rt_event);
1165}
1166
1167
b9626ec6
MM
1168struct rtable_config *
1169rt_new_table(struct symbol *s)
1170{
1171 struct rtable_config *c = cfg_allocz(sizeof(struct rtable_config));
1172
1173 cf_define_symbol(s, SYM_TABLE, c);
1174 c->name = s->name;
1175 add_tail(&new_config->tables, &c->n);
2eca3b3a 1176 c->gc_max_ops = 1000;
b9626ec6
MM
1177 c->gc_min_time = 5;
1178 return c;
1179}
1180
58740ed4
MM
1181/**
1182 * rt_lock_table - lock a routing table
1183 * @r: routing table to be locked
1184 *
1185 * Lock a routing table, because it's in use by a protocol,
1186 * preventing it from being freed when it gets undefined in a new
1187 * configuration.
1188 */
0e02abfd 1189void
50fe90ed 1190rt_lock_table(rtable *r)
0e02abfd 1191{
50fe90ed
MM
1192 r->use_count++;
1193}
1194
58740ed4
MM
1195/**
1196 * rt_unlock_table - unlock a routing table
1197 * @r: routing table to be unlocked
1198 *
1199 * Unlock a routing table formerly locked by rt_lock_table(),
1200 * that is decrease its use count and delete it if it's scheduled
1201 * for deletion by configuration changes.
1202 */
50fe90ed
MM
1203void
1204rt_unlock_table(rtable *r)
1205{
1206 if (!--r->use_count && r->deleted)
1207 {
1208 struct config *conf = r->deleted;
1209 DBG("Deleting routing table %s\n", r->name);
cfe34a31
OZ
1210 if (r->hostcache)
1211 rt_free_hostcache(r);
50fe90ed
MM
1212 rem_node(&r->n);
1213 fib_free(&r->fib);
cfe34a31 1214 rfree(r->rt_event);
50fe90ed
MM
1215 mb_free(r);
1216 config_del_obstacle(conf);
1217 }
1218}
1219
58740ed4
MM
1220/**
1221 * rt_commit - commit new routing table configuration
1222 * @new: new configuration
1223 * @old: original configuration or %NULL if it's boot time config
1224 *
1225 * Scan differences between @old and @new configuration and modify
1226 * the routing tables according to these changes. If @new defines a
1227 * previously unknown table, create it, if it omits a table existing
1228 * in @old, schedule it for deletion (it gets deleted when all protocols
1229 * disconnect from it by calling rt_unlock_table()), if it exists
1230 * in both configurations, leave it unchanged.
1231 */
50fe90ed
MM
1232void
1233rt_commit(struct config *new, struct config *old)
1234{
1235 struct rtable_config *o, *r;
0e02abfd 1236
50fe90ed
MM
1237 DBG("rt_commit:\n");
1238 if (old)
0e02abfd 1239 {
50fe90ed
MM
1240 WALK_LIST(o, old->tables)
1241 {
1242 rtable *ot = o->table;
1243 if (!ot->deleted)
1244 {
1245 struct symbol *sym = cf_find_symbol(o->name);
bf8558bc 1246 if (sym && sym->class == SYM_TABLE && !new->shutdown)
50fe90ed
MM
1247 {
1248 DBG("\t%s: same\n", o->name);
1249 r = sym->def;
1250 r->table = ot;
1251 ot->name = r->name;
b9626ec6 1252 ot->config = r;
50fe90ed
MM
1253 }
1254 else
1255 {
bf8558bc 1256 DBG("\t%s: deleted\n", o->name);
50fe90ed
MM
1257 ot->deleted = old;
1258 config_add_obstacle(old);
1259 rt_lock_table(ot);
1260 rt_unlock_table(ot);
1261 }
1262 }
1263 }
0e02abfd 1264 }
50fe90ed
MM
1265
1266 WALK_LIST(r, new->tables)
1267 if (!r->table)
1268 {
1269 rtable *t = mb_alloc(rt_table_pool, sizeof(struct rtable));
1270 DBG("\t%s: created\n", r->name);
b9626ec6 1271 rt_setup(rt_table_pool, t, r->name, r);
50fe90ed
MM
1272 add_tail(&routing_tables, &t->n);
1273 r->table = t;
1274 }
1275 DBG("\tdone\n");
0e02abfd 1276}
730f2e2c 1277
23ac9e9a
OZ
1278static inline void
1279do_feed_baby(struct proto *p, int type, struct announce_hook *h, net *n, rte *e)
1280{
1281 struct proto *q = e->attrs->proto;
1282 ea_list *tmpa;
1283
1284 rte_update_lock();
1285 tmpa = q->make_tmp_attrs ? q->make_tmp_attrs(e, rte_update_pool) : NULL;
ff2857b0 1286 do_rte_announce(h, type, n, e, p->refeeding ? e : NULL, tmpa, p->refeeding);
23ac9e9a
OZ
1287 rte_update_unlock();
1288}
1289
58740ed4
MM
1290/**
1291 * rt_feed_baby - advertise routes to a new protocol
1292 * @p: protocol to be fed
1293 *
1294 * This function performs one pass of advertisement of routes to a newly
1295 * initialized protocol. It's called by the protocol code as long as it
1296 * has something to do. (We avoid transferring all the routes in single
1297 * pass in order not to monopolize CPU time.)
1298 */
ac5d8012
MM
1299int
1300rt_feed_baby(struct proto *p)
1301{
1302 struct announce_hook *h;
1303 struct fib_iterator *fit;
76dfda9e 1304 int max_feed = 256;
ac5d8012
MM
1305
1306 if (!p->feed_ahook) /* Need to initialize first */
1307 {
1308 if (!p->ahooks)
1309 return 1;
1310 DBG("Announcing routes to new protocol %s\n", p->name);
1311 p->feed_ahook = p->ahooks;
1312 fit = p->feed_iterator = mb_alloc(p->pool, sizeof(struct fib_iterator));
1313 goto next_hook;
1314 }
1315 fit = p->feed_iterator;
1316
1317again:
1318 h = p->feed_ahook;
1319 FIB_ITERATE_START(&h->table->fib, fit, fn)
1320 {
1321 net *n = (net *) fn;
258d0ad4 1322 rte *e = n->routes;
76dfda9e
MM
1323 if (max_feed <= 0)
1324 {
1325 FIB_ITERATE_PUT(fit, fn);
1326 return 0;
1327 }
23ac9e9a
OZ
1328
1329 if (p->accept_ra_types == RA_OPTIMAL)
1330 if (e)
1331 {
1332 if (p->core_state != FS_FEEDING)
1333 return 1; /* In the meantime, the protocol fell down. */
1334 do_feed_baby(p, RA_OPTIMAL, h, n, e);
1335 max_feed--;
1336 }
1337
1338 if (p->accept_ra_types == RA_ANY)
1339 for(e = n->routes; e != NULL; e = e->next)
1340 {
1341 if (p->core_state != FS_FEEDING)
1342 return 1; /* In the meantime, the protocol fell down. */
1343 do_feed_baby(p, RA_ANY, h, n, e);
1344 max_feed--;
1345 }
ac5d8012
MM
1346 }
1347 FIB_ITERATE_END(fn);
1348 p->feed_ahook = h->next;
1349 if (!p->feed_ahook)
1350 {
1351 mb_free(p->feed_iterator);
1352 p->feed_iterator = NULL;
1353 return 1;
1354 }
1355
1356next_hook:
1357 h = p->feed_ahook;
1358 FIB_ITERATE_INIT(fit, &h->table->fib);
1359 goto again;
1360}
1361
58740ed4
MM
1362/**
1363 * rt_feed_baby_abort - abort protocol feeding
1364 * @p: protocol
1365 *
1366 * This function is called by the protocol code when the protocol
1367 * stops or ceases to exist before the last iteration of rt_feed_baby()
1368 * has finished.
1369 */
ac5d8012
MM
1370void
1371rt_feed_baby_abort(struct proto *p)
1372{
1373 if (p->feed_ahook)
1374 {
1375 /* Unlink the iterator and exit */
1376 fit_get(&p->feed_ahook->table->fib, p->feed_iterator);
1377 p->feed_ahook = NULL;
1378 }
1379}
1380
f2b76f2c
OZ
1381
1382static inline unsigned
1383ptr_hash(void *ptr)
1384{
1385 uintptr_t p = (uintptr_t) ptr;
1386 return p ^ (p << 8) ^ (p >> 16);
1387}
1388
1389static inline unsigned
1390hc_hash(ip_addr a, rtable *dep)
1391{
1392 return (ipa_hash(a) ^ ptr_hash(dep)) & 0xffff;
1393}
1394
1395static inline void
1396hc_insert(struct hostcache *hc, struct hostentry *he)
1397{
1398 unsigned int k = he->hash_key >> hc->hash_shift;
1399 he->next = hc->hash_table[k];
1400 hc->hash_table[k] = he;
1401}
1402
1403static inline void
1404hc_remove(struct hostcache *hc, struct hostentry *he)
1405{
1406 struct hostentry **hep;
1407 unsigned int k = he->hash_key >> hc->hash_shift;
1408
1409 for (hep = &hc->hash_table[k]; *hep != he; hep = &(*hep)->next);
1410 *hep = he->next;
1411}
1412
1413#define HC_DEF_ORDER 10
1414#define HC_HI_MARK *4
1415#define HC_HI_STEP 2
1416#define HC_HI_ORDER 16 /* Must be at most 16 */
1417#define HC_LO_MARK /5
1418#define HC_LO_STEP 2
1419#define HC_LO_ORDER 10
1420
1421static void
1422hc_alloc_table(struct hostcache *hc, unsigned order)
1423{
1424 unsigned hsize = 1 << order;
1425 hc->hash_order = order;
1426 hc->hash_shift = 16 - order;
1427 hc->hash_max = (order >= HC_HI_ORDER) ? ~0 : (hsize HC_HI_MARK);
1428 hc->hash_min = (order <= HC_LO_ORDER) ? 0 : (hsize HC_LO_MARK);
1429
1430 hc->hash_table = mb_allocz(rt_table_pool, hsize * sizeof(struct hostentry *));
1431}
1432
cfe34a31 1433static void
f2b76f2c 1434hc_resize(struct hostcache *hc, unsigned new_order)
cfe34a31 1435{
f2b76f2c
OZ
1436 unsigned old_size = 1 << hc->hash_order;
1437 struct hostentry **old_table = hc->hash_table;
1438 struct hostentry *he, *hen;
1439 int i;
1440
1441 hc_alloc_table(hc, new_order);
1442 for (i = 0; i < old_size; i++)
1443 for (he = old_table[i]; he != NULL; he=hen)
1444 {
1445 hen = he->next;
1446 hc_insert(hc, he);
1447 }
1448 mb_free(old_table);
1449}
1450
1451static struct hostentry *
1b180121 1452hc_new_hostentry(struct hostcache *hc, ip_addr a, ip_addr ll, rtable *dep, unsigned k)
f2b76f2c
OZ
1453{
1454 struct hostentry *he = sl_alloc(hc->slab);
1455
1456 he->addr = a;
1b180121 1457 he->link = ll;
f2b76f2c
OZ
1458 he->tab = dep;
1459 he->hash_key = k;
1460 he->uc = 0;
7e95c05d 1461 he->src = NULL;
f2b76f2c
OZ
1462
1463 add_tail(&hc->hostentries, &he->ln);
1464 hc_insert(hc, he);
1465
1466 hc->hash_items++;
1467 if (hc->hash_items > hc->hash_max)
1468 hc_resize(hc, hc->hash_order + HC_HI_STEP);
1469
1470 return he;
1471}
1472
1473static void
1474hc_delete_hostentry(struct hostcache *hc, struct hostentry *he)
1475{
7e95c05d
OZ
1476 rta_free(he->src);
1477
f2b76f2c
OZ
1478 rem_node(&he->ln);
1479 hc_remove(hc, he);
1480 sl_free(hc->slab, he);
1481
1482 hc->hash_items--;
1483 if (hc->hash_items < hc->hash_min)
1484 hc_resize(hc, hc->hash_order - HC_LO_STEP);
cfe34a31
OZ
1485}
1486
1487static void
1488rt_init_hostcache(rtable *tab)
1489{
1490 struct hostcache *hc = mb_allocz(rt_table_pool, sizeof(struct hostcache));
1491 init_list(&hc->hostentries);
f2b76f2c
OZ
1492
1493 hc->hash_items = 0;
1494 hc_alloc_table(hc, HC_DEF_ORDER);
1495 hc->slab = sl_new(rt_table_pool, sizeof(struct hostentry));
1496
c477f489
OZ
1497 hc->lp = lp_new(rt_table_pool, 1008);
1498 hc->trie = f_new_trie(hc->lp);
1499
cfe34a31
OZ
1500 tab->hostcache = hc;
1501}
1502
1503static void
1504rt_free_hostcache(rtable *tab)
1505{
1506 struct hostcache *hc = tab->hostcache;
1507
1508 node *n;
1509 WALK_LIST(n, hc->hostentries)
1510 {
1511 struct hostentry *he = SKIP_BACK(struct hostentry, ln, n);
7e95c05d
OZ
1512 rta_free(he->src);
1513
cfe34a31
OZ
1514 if (he->uc)
1515 log(L_ERR "Hostcache is not empty in table %s", tab->name);
1516 }
1517
f2b76f2c 1518 rfree(hc->slab);
c477f489 1519 rfree(hc->lp);
f2b76f2c 1520 mb_free(hc->hash_table);
cfe34a31
OZ
1521 mb_free(hc);
1522}
1523
1524static void
1525rt_notify_hostcache(rtable *tab, net *net)
1526{
1527 struct hostcache *hc = tab->hostcache;
1528
1529 if (tab->hcu_scheduled)
1530 return;
1531
c477f489
OZ
1532 if (trie_match_prefix(hc->trie, net->n.prefix, net->n.pxlen))
1533 rt_schedule_hcu(tab);
cfe34a31
OZ
1534}
1535
1536static int
1537if_local_addr(ip_addr a, struct iface *i)
1538{
1539 struct ifa *b;
1540
1541 WALK_LIST(b, i->addrs)
1542 if (ipa_equal(a, b->ip))
1543 return 1;
1544
1545 return 0;
1546}
1547
d1e146f2
OZ
1548static u32
1549rt_get_igp_metric(rte *rt)
1550{
ba5e5940
OZ
1551 eattr *ea = ea_find(rt->attrs->eattrs, EA_GEN_IGP_METRIC);
1552
1553 if (ea)
1554 return ea->u.data;
1555
d1e146f2 1556 rta *a = rt->attrs;
b7c48981
OF
1557
1558#ifdef CONFIG_OSPF
d1e146f2
OZ
1559 if ((a->source == RTS_OSPF) ||
1560 (a->source == RTS_OSPF_IA) ||
1561 (a->source == RTS_OSPF_EXT1))
1562 return rt->u.ospf.metric1;
b7c48981 1563#endif
d1e146f2 1564
b7c48981 1565#ifdef CONFIG_RIP
d1e146f2
OZ
1566 if (a->source == RTS_RIP)
1567 return rt->u.rip.metric;
b7c48981 1568#endif
d1e146f2
OZ
1569
1570 /* Device routes */
7e95c05d 1571 if ((a->dest != RTD_ROUTER) && (a->dest != RTD_MULTIPATH))
d1e146f2
OZ
1572 return 0;
1573
1574 return IGP_METRIC_UNKNOWN;
1575}
1576
cfe34a31
OZ
1577static int
1578rt_update_hostentry(rtable *tab, struct hostentry *he)
1579{
7e95c05d 1580 rta *old_src = he->src;
c477f489 1581 int pxlen = 0;
cfe34a31 1582
7e95c05d
OZ
1583 /* Reset the hostentry */
1584 he->src = NULL;
1585 he->gw = IPA_NONE;
1586 he->dest = RTD_UNREACHABLE;
1587 he->igp_metric = 0;
1588
d1e146f2
OZ
1589 net *n = net_route(tab, he->addr, MAX_PREFIX_LENGTH);
1590 if (n)
cfe34a31
OZ
1591 {
1592 rta *a = n->routes->attrs;
c477f489 1593 pxlen = n->n.pxlen;
cfe34a31 1594
2c9033af
OZ
1595 if (a->hostentry)
1596 {
1597 /* Recursive route should not depend on another recursive route */
1598 log(L_WARN "Next hop address %I resolvable through recursive route for %I/%d",
7e95c05d
OZ
1599 he->addr, n->n.prefix, pxlen);
1600 goto done;
2c9033af 1601 }
7e95c05d
OZ
1602
1603 if (a->dest == RTD_DEVICE)
cfe34a31 1604 {
f2b76f2c 1605 if (if_local_addr(he->addr, a->iface))
cfe34a31
OZ
1606 {
1607 /* The host address is a local address, this is not valid */
1608 log(L_WARN "Next hop address %I is a local address of iface %s",
f2b76f2c 1609 he->addr, a->iface->name);
7e95c05d 1610 goto done;
cfe34a31 1611 }
7e95c05d
OZ
1612
1613 /* The host is directly reachable, use link as a gateway */
1614 he->gw = he->link;
1615 he->dest = RTD_ROUTER;
cfe34a31
OZ
1616 }
1617 else
1618 {
1619 /* The host is reachable through some route entry */
cfe34a31
OZ
1620 he->gw = a->gw;
1621 he->dest = a->dest;
1622 }
d1e146f2 1623
7e95c05d
OZ
1624 he->src = rta_clone(a);
1625 he->igp_metric = rt_get_igp_metric(n->routes);
cfe34a31
OZ
1626 }
1627
7e95c05d 1628 done:
c477f489
OZ
1629 /* Add a prefix range to the trie */
1630 trie_add_prefix(tab->hostcache->trie, he->addr, MAX_PREFIX_LENGTH, pxlen, MAX_PREFIX_LENGTH);
1631
7e95c05d
OZ
1632 rta_free(old_src);
1633 return old_src != he->src;
cfe34a31
OZ
1634}
1635
1636static void
1637rt_update_hostcache(rtable *tab)
1638{
1639 struct hostcache *hc = tab->hostcache;
1640 struct hostentry *he;
1641 node *n, *x;
1642
c477f489
OZ
1643 /* Reset the trie */
1644 lp_flush(hc->lp);
1645 hc->trie = f_new_trie(hc->lp);
1646
cfe34a31
OZ
1647 WALK_LIST_DELSAFE(n, x, hc->hostentries)
1648 {
1649 he = SKIP_BACK(struct hostentry, ln, n);
1650 if (!he->uc)
1651 {
f2b76f2c 1652 hc_delete_hostentry(hc, he);
cfe34a31
OZ
1653 continue;
1654 }
1655
1656 if (rt_update_hostentry(tab, he))
1657 rt_schedule_nhu(he->tab);
1658 }
1659
1660 tab->hcu_scheduled = 0;
1661}
1662
1663static struct hostentry *
1b180121 1664rt_find_hostentry(rtable *tab, ip_addr a, ip_addr ll, rtable *dep)
cfe34a31
OZ
1665{
1666 struct hostentry *he;
1667
1668 if (!tab->hostcache)
1669 rt_init_hostcache(tab);
1670
f2b76f2c
OZ
1671 unsigned int k = hc_hash(a, dep);
1672 struct hostcache *hc = tab->hostcache;
1673 for (he = hc->hash_table[k >> hc->hash_shift]; he != NULL; he = he->next)
1674 if (ipa_equal(he->addr, a) && (he->tab == dep))
1675 return he;
cfe34a31 1676
1b180121 1677 he = hc_new_hostentry(hc, a, ll, dep, k);
f2b76f2c 1678 rt_update_hostentry(tab, he);
cfe34a31
OZ
1679 return he;
1680}
1681
1682void
1b180121 1683rta_set_recursive_next_hop(rtable *dep, rta *a, rtable *tab, ip_addr *gw, ip_addr *ll)
cfe34a31 1684{
1b180121 1685 rta_apply_hostentry(a, rt_find_hostentry(tab, *gw, *ll, dep));
cfe34a31
OZ
1686}
1687
730f2e2c
MM
1688/*
1689 * CLI commands
1690 */
1691
1692static void
cfd46ee4 1693rt_format_via(rte *e, byte *via)
730f2e2c 1694{
730f2e2c
MM
1695 rta *a = e->attrs;
1696
1697 switch (a->dest)
1698 {
1699 case RTD_ROUTER: bsprintf(via, "via %I on %s", a->gw, a->iface->name); break;
1700 case RTD_DEVICE: bsprintf(via, "dev %s", a->iface->name); break;
1701 case RTD_BLACKHOLE: bsprintf(via, "blackhole"); break;
1702 case RTD_UNREACHABLE: bsprintf(via, "unreachable"); break;
1703 case RTD_PROHIBIT: bsprintf(via, "prohibited"); break;
7e95c05d 1704 case RTD_MULTIPATH: bsprintf(via, "multipath"); break;
730f2e2c
MM
1705 default: bsprintf(via, "???");
1706 }
cfd46ee4
MM
1707}
1708
1709static void
ce1da96e 1710rt_show_rte(struct cli *c, byte *ia, rte *e, struct rt_show_data *d, ea_list *tmpa)
cfd46ee4 1711{
4ca93a50 1712 byte via[STD_ADDRESS_P_LENGTH+32], from[STD_ADDRESS_P_LENGTH+8];
c37e7851 1713 byte tm[TM_DATETIME_BUFFER_SIZE], info[256];
cfd46ee4 1714 rta *a = e->attrs;
5a56f27c 1715 int primary = (e->net->routes == e);
32f95476 1716 int sync_error = (e->net->n.flags & KRF_SYNC_ERROR);
7e95c05d 1717 struct mpnh *nh;
cfd46ee4
MM
1718
1719 rt_format_via(e, via);
c37e7851 1720 tm_format_datetime(tm, &config->tf_route, e->lastmod);
730f2e2c
MM
1721 if (ipa_nonzero(a->from) && !ipa_equal(a->from, a->gw))
1722 bsprintf(from, " from %I", a->from);
1723 else
1724 from[0] = 0;
ce1da96e
MM
1725 if (a->proto->proto->get_route_info || d->verbose)
1726 {
1727 /* Need to normalize the extended attributes */
1728 ea_list *t = tmpa;
1729 t = ea_append(t, a->eattrs);
1730 tmpa = alloca(ea_scan(t));
1731 ea_merge(t, tmpa);
2f711231 1732 ea_sort(tmpa);
ce1da96e 1733 }
730f2e2c 1734 if (a->proto->proto->get_route_info)
ce1da96e 1735 a->proto->proto->get_route_info(e, info, tmpa);
730f2e2c
MM
1736 else
1737 bsprintf(info, " (%d)", e->pref);
5a56f27c 1738 cli_printf(c, -1007, "%-18s %s [%s %s%s]%s%s", ia, via, a->proto->name,
32f95476 1739 tm, from, primary ? (sync_error ? " !" : " *") : "", info);
7e95c05d
OZ
1740 for (nh = a->nexthops; nh; nh = nh->next)
1741 cli_printf(c, -1007, "\tvia %I on %s weight %d", nh->gw, nh->iface->name, nh->weight + 1);
730f2e2c 1742 if (d->verbose)
ce1da96e 1743 rta_show(c, a, tmpa);
730f2e2c
MM
1744}
1745
1746static void
1747rt_show_net(struct cli *c, net *n, struct rt_show_data *d)
1748{
1749 rte *e, *ee;
1750 byte ia[STD_ADDRESS_P_LENGTH+8];
c0adf7e9 1751 struct announce_hook *a;
ce1da96e 1752 int ok;
730f2e2c
MM
1753
1754 bsprintf(ia, "%I/%d", n->n.prefix, n->n.pxlen);
0d307082
MM
1755 if (n->routes)
1756 d->net_counter++;
730f2e2c
MM
1757 for(e=n->routes; e; e=e->next)
1758 {
ce1da96e
MM
1759 struct ea_list *tmpa, *old_tmpa;
1760 struct proto *p0 = e->attrs->proto;
ea2ae6dd 1761 struct proto *p1 = d->export_protocol;
4d176e14 1762 struct proto *p2 = d->show_protocol;
23693958 1763 d->rt_counter++;
730f2e2c
MM
1764 ee = e;
1765 rte_update_lock(); /* We use the update buffer for filtering */
ce1da96e
MM
1766 old_tmpa = tmpa = p0->make_tmp_attrs ? p0->make_tmp_attrs(e, rte_update_pool) : NULL;
1767 ok = (d->filter == FILTER_ACCEPT || f_run(d->filter, &e, &tmpa, rte_update_pool, FF_FORCE_TMPATTR) <= F_ACCEPT);
4d176e14 1768 if (p2 && p2 != p0) ok = 0;
ea2ae6dd 1769 if (ok && d->export_mode)
ce1da96e 1770 {
925fe2d3 1771 int ic;
ff2857b0 1772 if ((ic = p1->import_control ? p1->import_control(p1, &e, &tmpa, rte_update_pool) : 0) < 0)
ce1da96e 1773 ok = 0;
ea2ae6dd 1774 else if (!ic && d->export_mode > 1)
ce1da96e 1775 {
bf47fe4b
OZ
1776 /* FIXME - this shows what should be exported according
1777 to current filters, but not what was really exported.
1778 'configure soft' command may change the export filter
1779 and do not update routes */
1780
c0adf7e9
OZ
1781 if ((a = proto_find_announce_hook(p1, d->table)) && ((a->out_filter == FILTER_REJECT) ||
1782 (a->out_filter && f_run(a->out_filter, &e, &tmpa, rte_update_pool, FF_FORCE_TMPATTR) > F_ACCEPT)))
ce1da96e
MM
1783 ok = 0;
1784 }
1785 }
1786 if (ok)
730f2e2c 1787 {
23693958 1788 d->show_counter++;
33a368ad
MM
1789 if (d->stats < 2)
1790 rt_show_rte(c, ia, e, d, tmpa);
730f2e2c
MM
1791 ia[0] = 0;
1792 }
1793 if (e != ee)
5e9bdac2
OZ
1794 {
1795 rte_free(e);
1796 e = ee;
1797 }
730f2e2c 1798 rte_update_unlock();
0117d004 1799 if (d->primary_only)
ce1da96e 1800 break;
730f2e2c
MM
1801 }
1802}
1803
1804static void
1805rt_show_cont(struct cli *c)
1806{
1807 struct rt_show_data *d = c->rover;
f098e072
MM
1808#ifdef DEBUGGING
1809 unsigned max = 4;
1810#else
1811 unsigned max = 64;
1812#endif
730f2e2c
MM
1813 struct fib *fib = &d->table->fib;
1814 struct fib_iterator *it = &d->fit;
1815
1816 FIB_ITERATE_START(fib, it, f)
1817 {
1818 net *n = (net *) f;
ce1da96e
MM
1819 if (d->running_on_config && d->running_on_config != config)
1820 {
1821 cli_printf(c, 8004, "Stopped due to reconfiguration");
1822 goto done;
1823 }
ea2ae6dd
OZ
1824 if (d->export_protocol &&
1825 d->export_protocol->core_state != FS_HAPPY &&
1826 d->export_protocol->core_state != FS_FEEDING)
ce1da96e
MM
1827 {
1828 cli_printf(c, 8005, "Protocol is down");
1829 goto done;
1830 }
730f2e2c
MM
1831 if (!max--)
1832 {
1833 FIB_ITERATE_PUT(it, f);
1834 return;
1835 }
1836 rt_show_net(c, n, d);
1837 }
1838 FIB_ITERATE_END(f);
23693958
MM
1839 if (d->stats)
1840 cli_printf(c, 14, "%d of %d routes for %d networks", d->show_counter, d->rt_counter, d->net_counter);
1841 else
1842 cli_printf(c, 0, "");
ce1da96e 1843done:
730f2e2c
MM
1844 c->cont = c->cleanup = NULL;
1845}
1846
1847static void
1848rt_show_cleanup(struct cli *c)
1849{
1850 struct rt_show_data *d = c->rover;
1851
1852 /* Unlink the iterator */
1853 fit_get(&d->table->fib, &d->fit);
1854}
1855
1856void
1857rt_show(struct rt_show_data *d)
1858{
730f2e2c
MM
1859 net *n;
1860
1861 if (d->pxlen == 256)
1862 {
1863 FIB_ITERATE_INIT(&d->fit, &d->table->fib);
1864 this_cli->cont = rt_show_cont;
1865 this_cli->cleanup = rt_show_cleanup;
1866 this_cli->rover = d;
1867 }
1868 else
1869 {
9449c91a 1870 if (d->show_for)
d1e146f2 1871 n = net_route(d->table, d->prefix, d->pxlen);
9449c91a 1872 else
d1e146f2 1873 n = net_find(d->table, d->prefix, d->pxlen);
730f2e2c
MM
1874 if (n)
1875 {
1876 rt_show_net(this_cli, n, d);
1877 cli_msg(0, "");
1878 }
1879 else
1880 cli_msg(8001, "Network not in table");
1881 }
1882}
3ce8c610
MM
1883
1884/*
1885 * Documentation for functions declared inline in route.h
1886 */
1887#if 0
1888
1889/**
1890 * net_find - find a network entry
1891 * @tab: a routing table
1892 * @addr: address of the network
1893 * @len: length of the network prefix
1894 *
1895 * net_find() looks up the given network in routing table @tab and
1896 * returns a pointer to its &net entry or %NULL if no such network
1897 * exists.
1898 */
1899static inline net *net_find(rtable *tab, ip_addr addr, unsigned len)
1900{ DUMMY; }
1901
1902/**
1903 * net_get - obtain a network entry
1904 * @tab: a routing table
1905 * @addr: address of the network
1906 * @len: length of the network prefix
1907 *
1908 * net_get() looks up the given network in routing table @tab and
1909 * returns a pointer to its &net entry. If no such entry exists, it's
1910 * created.
1911 */
1912static inline net *net_get(rtable *tab, ip_addr addr, unsigned len)
1913{ DUMMY; }
1914
1915/**
1916 * rte_cow - copy a route for writing
1917 * @r: a route entry to be copied
1918 *
1919 * rte_cow() takes a &rte and prepares it for modification. The exact action
1920 * taken depends on the flags of the &rte -- if it's a temporary entry, it's
1921 * just returned unchanged, else a new temporary entry with the same contents
1922 * is created.
1923 *
1924 * The primary use of this function is inside the filter machinery -- when
1925 * a filter wants to modify &rte contents (to change the preference or to
1926 * attach another set of attributes), it must ensure that the &rte is not
1927 * shared with anyone else (and especially that it isn't stored in any routing
1928 * table).
1929 *
2e9b2421 1930 * Result: a pointer to the new writable &rte.
3ce8c610
MM
1931 */
1932static inline rte * rte_cow(rte *r)
1933{ DUMMY; }
1934
1935#endif