]> git.ipfire.org Git - thirdparty/bird.git/blob - nest/rt-table.c
Implements command that shows memory usage.
[thirdparty/bird.git] / nest / rt-table.c
1 /*
2 * BIRD -- Routing Tables
3 *
4 * (c) 1998--2000 Martin Mares <mj@ucw.cz>
5 *
6 * Can be freely distributed and used under the terms of the GNU GPL.
7 */
8
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 *
16 * There are multiple routing tables (a primary one together with any
17 * number of secondary ones if requested by the configuration). Each table
18 * is basically a FIB containing entries describing the individual
19 * destination networks. For each network (represented by structure &net),
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
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
31 #undef LOCAL_DEBUG
32
33 #include "nest/bird.h"
34 #include "nest/route.h"
35 #include "nest/protocol.h"
36 #include "nest/cli.h"
37 #include "nest/iface.h"
38 #include "lib/resource.h"
39 #include "lib/event.h"
40 #include "lib/string.h"
41 #include "conf/conf.h"
42 #include "filter/filter.h"
43 #include "lib/string.h"
44 #include "lib/alloca.h"
45
46 pool *rt_table_pool;
47
48 static slab *rte_slab;
49 static linpool *rte_update_pool;
50
51 static list routing_tables;
52
53 static void rt_format_via(rte *e, byte *via);
54
55 static void
56 rte_init(struct fib_node *N)
57 {
58 net *n = (net *) N;
59
60 N->flags = 0;
61 n->routes = NULL;
62 }
63
64 /**
65 * rte_find - find a route
66 * @net: network node
67 * @p: protocol
68 *
69 * The rte_find() function returns a route for destination @net
70 * which belongs has been defined by protocol @p.
71 */
72 rte *
73 rte_find(net *net, struct proto *p)
74 {
75 rte *e = net->routes;
76
77 while (e && e->attrs->proto != p)
78 e = e->next;
79 return e;
80 }
81
82 /**
83 * rte_get_temp - get a temporary &rte
84 * @a: attributes to assign to the new route (a &rta; in case it's
85 * un-cached, rte_update() will create a cached copy automatically)
86 *
87 * Create a temporary &rte and bind it with the attributes @a.
88 * Also set route preference to the default preference set for
89 * the protocol.
90 */
91 rte *
92 rte_get_temp(rta *a)
93 {
94 rte *e = sl_alloc(rte_slab);
95
96 e->attrs = a;
97 e->flags = 0;
98 e->pref = a->proto->preference;
99 return e;
100 }
101
102 rte *
103 rte_do_cow(rte *r)
104 {
105 rte *e = sl_alloc(rte_slab);
106
107 memcpy(e, r, sizeof(rte));
108 e->attrs = rta_clone(r->attrs);
109 e->flags = 0;
110 return e;
111 }
112
113 static int /* Actually better or at least as good as */
114 rte_better(rte *new, rte *old)
115 {
116 int (*better)(rte *, rte *);
117
118 if (!old)
119 return 1;
120 if (new->pref > old->pref)
121 return 1;
122 if (new->pref < old->pref)
123 return 0;
124 if (new->attrs->proto->proto != old->attrs->proto->proto)
125 {
126 /*
127 * If the user has configured protocol preferences, so that two different protocols
128 * have the same preference, try to break the tie by comparing addresses. Not too
129 * useful, but keeps the ordering of routes unambiguous.
130 */
131 return new->attrs->proto->proto > old->attrs->proto->proto;
132 }
133 if (better = new->attrs->proto->rte_better)
134 return better(new, old);
135 return 0;
136 }
137
138 static void
139 rte_trace(struct proto *p, rte *e, int dir, char *msg)
140 {
141 byte via[STD_ADDRESS_P_LENGTH+32];
142
143 rt_format_via(e, via);
144 log(L_TRACE "%s %c %s %I/%d %s", p->name, dir, msg, e->net->n.prefix, e->net->n.pxlen, via);
145 }
146
147 static inline void
148 rte_trace_in(unsigned int flag, struct proto *p, rte *e, char *msg)
149 {
150 if (p->debug & flag)
151 rte_trace(p, e, '>', msg);
152 }
153
154 static inline void
155 rte_trace_out(unsigned int flag, struct proto *p, rte *e, char *msg)
156 {
157 if (p->debug & flag)
158 rte_trace(p, e, '<', msg);
159 }
160
161 static inline void
162 do_rte_announce(struct announce_hook *a, int type UNUSED, net *net, rte *new, rte *old, ea_list *tmpa, int refeed)
163 {
164 struct proto *p = a->proto;
165 struct filter *filter = p->out_filter;
166 struct proto_stats *stats = &p->stats;
167 rte *new0 = new;
168 rte *old0 = old;
169 int ok;
170
171 #ifdef CONFIG_PIPE
172 /* The secondary direction of the pipe */
173 if (proto_is_pipe(p) && (p->table != a->table))
174 {
175 filter = p->in_filter;
176 stats = pipe_get_peer_stats(p);
177 }
178 #endif
179
180 if (new)
181 {
182 stats->exp_updates_received++;
183
184 char *drop_reason = NULL;
185 if ((ok = p->import_control ? p->import_control(p, &new, &tmpa, rte_update_pool) : 0) < 0)
186 {
187 stats->exp_updates_rejected++;
188 drop_reason = "rejected by protocol";
189 }
190 else if (ok)
191 rte_trace_out(D_FILTERS, p, new, "forced accept by protocol");
192 else if ((filter == FILTER_REJECT) ||
193 (filter && f_run(filter, &new, &tmpa, rte_update_pool, FF_FORCE_TMPATTR) > F_ACCEPT))
194 {
195 stats->exp_updates_filtered++;
196 drop_reason = "filtered out";
197 }
198 if (drop_reason)
199 {
200 rte_trace_out(D_FILTERS, p, new, drop_reason);
201 if (new != new0)
202 rte_free(new);
203 new = NULL;
204 }
205 }
206 else
207 stats->exp_withdraws_received++;
208
209 /*
210 * This is a tricky part - we don't know whether route 'old' was
211 * exported to protocol 'p' or was filtered by the export filter.
212 * We try tu run the export filter to know this to have a correct
213 * value in 'old' argument of rt_update (and proper filter value)
214 *
215 * FIXME - this is broken because 'configure soft' may change
216 * filters but keep routes. Refeed is expected to be called after
217 * change of the filters and with old == new, therefore we do not
218 * even try to run the filter on an old route, This may lead to
219 * 'spurious withdraws' but ensure that there are no 'missing
220 * withdraws'.
221 *
222 * This is not completely safe as there is a window between
223 * reconfiguration and the end of refeed - if a newly filtered
224 * route disappears during this period, proper withdraw is not
225 * sent (because old would be also filtered) and the route is
226 * not refeeded (because it disappeared before that).
227 */
228
229 if (old && !refeed)
230 {
231 if (filter == FILTER_REJECT)
232 old = NULL;
233 else
234 {
235 ea_list *tmpb = p->make_tmp_attrs ? p->make_tmp_attrs(old, rte_update_pool) : NULL;
236 ok = p->import_control ? p->import_control(p, &old, &tmpb, rte_update_pool) : 0;
237 if (ok < 0 || (!ok && filter && f_run(filter, &old, &tmpb, rte_update_pool, FF_FORCE_TMPATTR) > F_ACCEPT))
238 {
239 if (old != old0)
240 rte_free(old);
241 old = NULL;
242 }
243 }
244 }
245
246 /* FIXME - This is broken because of incorrect 'old' value (see above) */
247 if (!new && !old)
248 return;
249
250 if (new)
251 stats->exp_updates_accepted++;
252 else
253 stats->exp_withdraws_accepted++;
254
255 /* Hack: We do not decrease exp_routes during refeed, we instead
256 reset exp_routes at the start of refeed. */
257 if (new)
258 stats->exp_routes++;
259 if (old && !refeed)
260 stats->exp_routes--;
261
262 if (p->debug & D_ROUTES)
263 {
264 if (new && old)
265 rte_trace_out(D_ROUTES, p, new, "replaced");
266 else if (new)
267 rte_trace_out(D_ROUTES, p, new, "added");
268 else if (old)
269 rte_trace_out(D_ROUTES, p, old, "removed");
270 }
271 if (!new)
272 p->rt_notify(p, a->table, net, NULL, old, NULL);
273 else if (tmpa)
274 {
275 ea_list *t = tmpa;
276 while (t->next)
277 t = t->next;
278 t->next = new->attrs->eattrs;
279 p->rt_notify(p, a->table, net, new, old, tmpa);
280 t->next = NULL;
281 }
282 else
283 p->rt_notify(p, a->table, net, new, old, new->attrs->eattrs);
284 if (new && new != new0) /* Discard temporary rte's */
285 rte_free(new);
286 if (old && old != old0)
287 rte_free(old);
288 }
289
290 /**
291 * rte_announce - announce a routing table change
292 * @tab: table the route has been added to
293 * @type: type of route announcement (RA_OPTIMAL or RA_ANY)
294 * @net: network in question
295 * @new: the new route to be announced
296 * @old: the previous route for the same network
297 * @tmpa: a list of temporary attributes belonging to the new route
298 *
299 * This function gets a routing table update and announces it
300 * to all protocols that acccepts given type of route announcement
301 * and are connected to the same table by their announcement hooks.
302 *
303 * Route announcement of type RA_OPTIMAL si generated when optimal
304 * route (in routing table @tab) changes. In that case @old stores the
305 * old optimal route.
306 *
307 * Route announcement of type RA_ANY si generated when any route (in
308 * routing table @tab) changes In that case @old stores the old route
309 * from the same protocol.
310 *
311 * For each appropriate protocol, we first call its import_control()
312 * hook which performs basic checks on the route (each protocol has a
313 * right to veto or force accept of the route before any filter is
314 * asked) and adds default values of attributes specific to the new
315 * protocol (metrics, tags etc.). Then it consults the protocol's
316 * export filter and if it accepts the route, the rt_notify() hook of
317 * the protocol gets called.
318 */
319 static void
320 rte_announce(rtable *tab, unsigned type, net *net, rte *new, rte *old, ea_list *tmpa)
321 {
322 struct announce_hook *a;
323
324 if (type == RA_OPTIMAL)
325 {
326 if (new)
327 new->attrs->proto->stats.pref_routes++;
328 if (old)
329 old->attrs->proto->stats.pref_routes--;
330 }
331
332 WALK_LIST(a, tab->hooks)
333 {
334 ASSERT(a->proto->core_state == FS_HAPPY || a->proto->core_state == FS_FEEDING);
335 if (a->proto->accept_ra_types == type)
336 do_rte_announce(a, type, net, new, old, tmpa, 0);
337 }
338 }
339
340 static inline int
341 rte_validate(rte *e)
342 {
343 int c;
344 net *n = e->net;
345
346 if (ipa_nonzero(ipa_and(n->n.prefix, ipa_not(ipa_mkmask(n->n.pxlen)))))
347 {
348 log(L_BUG "Ignoring bogus prefix %I/%d received via %s",
349 n->n.prefix, n->n.pxlen, e->sender->name);
350 return 0;
351 }
352
353 c = ipa_classify_net(n->n.prefix);
354 if ((c < 0) || !(c & IADDR_HOST) || ((c & IADDR_SCOPE_MASK) <= SCOPE_LINK))
355 {
356 log(L_WARN "Ignoring bogus route %I/%d received via %s",
357 n->n.prefix, n->n.pxlen, e->sender->name);
358 return 0;
359 }
360
361 return 1;
362 }
363
364 /**
365 * rte_free - delete a &rte
366 * @e: &rte to be deleted
367 *
368 * rte_free() deletes the given &rte from the routing table it's linked to.
369 */
370 void
371 rte_free(rte *e)
372 {
373 if (e->attrs->aflags & RTAF_CACHED)
374 rta_free(e->attrs);
375 sl_free(rte_slab, e);
376 }
377
378 static inline void
379 rte_free_quick(rte *e)
380 {
381 rta_free(e->attrs);
382 sl_free(rte_slab, e);
383 }
384
385 static int
386 rte_same(rte *x, rte *y)
387 {
388 return
389 x->attrs == y->attrs &&
390 x->flags == y->flags &&
391 x->pflags == y->pflags &&
392 x->pref == y->pref &&
393 (!x->attrs->proto->rte_same || x->attrs->proto->rte_same(x, y));
394 }
395
396 static void
397 rte_recalculate(rtable *table, net *net, struct proto *p, struct proto *src, rte *new, ea_list *tmpa)
398 {
399 struct proto_stats *stats = &p->stats;
400 rte *old_best = net->routes;
401 rte *old = NULL;
402 rte **k, *r, *s;
403
404 #ifdef CONFIG_PIPE
405 if (proto_is_pipe(p) && (p->table == table))
406 stats = pipe_get_peer_stats(p);
407 #endif
408
409 k = &net->routes; /* Find and remove original route from the same protocol */
410 while (old = *k)
411 {
412 if (old->attrs->proto == src)
413 {
414 /* If there is the same route in the routing table but from
415 * a different sender, then there are two paths from the
416 * source protocol to this routing table through transparent
417 * pipes, which is not allowed.
418 *
419 * We log that and ignore the route. If it is withdraw, we
420 * ignore it completely (there might be 'spurious withdraws',
421 * see FIXME in do_rte_announce())
422 */
423 if (old->sender != p)
424 {
425 if (new)
426 {
427 log(L_ERR "Pipe collision detected when sending %I/%d to table %s",
428 net->n.prefix, net->n.pxlen, table->name);
429 rte_free_quick(new);
430 }
431 return;
432 }
433
434 if (new && rte_same(old, new))
435 {
436 /* No changes, ignore the new route */
437 stats->imp_updates_ignored++;
438 rte_trace_in(D_ROUTES, p, new, "ignored");
439 rte_free_quick(new);
440 #ifdef CONFIG_RIP
441 /* lastmod is used internally by RIP as the last time
442 when the route was received. */
443 if (src->proto == &proto_rip)
444 old->lastmod = now;
445 #endif
446 return;
447 }
448 *k = old->next;
449 break;
450 }
451 k = &old->next;
452 }
453
454 if (!old && !new)
455 {
456 stats->imp_withdraws_ignored++;
457 return;
458 }
459
460 if (new)
461 stats->imp_updates_accepted++;
462 else
463 stats->imp_withdraws_accepted++;
464
465 if (new)
466 stats->imp_routes++;
467 if (old)
468 stats->imp_routes--;
469
470 rte_announce(table, RA_ANY, net, new, old, tmpa);
471
472
473 if (new && rte_better(new, old_best))
474 {
475 /* The first case - the new route is cleary optimal, we link it
476 at the first position and announce it */
477
478 rte_trace_in(D_ROUTES, p, new, "added [best]");
479 rte_announce(table, RA_OPTIMAL, net, new, old_best, tmpa);
480 new->next = net->routes;
481 net->routes = new;
482 }
483 else if (old == old_best)
484 {
485 /* The second case - the old best route disappeared, we add the
486 new route (if we have any) to the list (we don't care about
487 position) and then we elect the new optimal route and relink
488 that route at the first position and announce it. New optimal
489 route might be NULL if there is no more routes */
490
491 /* Add the new route to the list */
492 if (new)
493 {
494 rte_trace_in(D_ROUTES, p, new, "added");
495 new->next = net->routes;
496 net->routes = new;
497 }
498
499 /* Find new optimal route */
500 r = NULL;
501 for (s=net->routes; s; s=s->next)
502 if (rte_better(s, r))
503 r = s;
504
505 /* Announce optimal route */
506 rte_announce(table, RA_OPTIMAL, net, r, old_best, tmpa);
507
508 /* And relink it (if there is any) */
509 if (r)
510 {
511 k = &net->routes;
512 while (s = *k)
513 {
514 if (s == r)
515 {
516 *k = r->next;
517 break;
518 }
519 k = &s->next;
520 }
521 r->next = net->routes;
522 net->routes = r;
523 }
524 else if (table->gc_counter++ >= table->config->gc_max_ops &&
525 table->gc_time + table->config->gc_min_time <= now)
526 ev_schedule(table->gc_event);
527 }
528 else if (new)
529 {
530 /* The third case - the new route is not better than the old
531 best route (therefore old_best != NULL) and the old best
532 route was not removed (therefore old_best == net->routes).
533 We just link the new route after the old best route. */
534
535 ASSERT(net->routes != NULL);
536 new->next = net->routes->next;
537 net->routes->next = new;
538 rte_trace_in(D_ROUTES, p, new, "added");
539 }
540
541 /* Log the route removal */
542 if (!new && old && (p->debug & D_ROUTES))
543 {
544 if (old != old_best)
545 rte_trace_in(D_ROUTES, p, old, "removed");
546 else if (net->routes)
547 rte_trace_in(D_ROUTES, p, old, "removed [replaced]");
548 else
549 rte_trace_in(D_ROUTES, p, old, "removed [sole]");
550 }
551
552 if (old)
553 {
554 if (p->rte_remove)
555 p->rte_remove(net, old);
556 rte_free_quick(old);
557 }
558 if (new)
559 {
560 new->lastmod = now;
561 if (p->rte_insert)
562 p->rte_insert(net, new);
563 }
564 }
565
566 static int rte_update_nest_cnt; /* Nesting counter to allow recursive updates */
567
568 static inline void
569 rte_update_lock(void)
570 {
571 rte_update_nest_cnt++;
572 }
573
574 static inline void
575 rte_update_unlock(void)
576 {
577 if (!--rte_update_nest_cnt)
578 lp_flush(rte_update_pool);
579 }
580
581 /**
582 * rte_update - enter a new update to a routing table
583 * @table: table to be updated
584 * @net: network node
585 * @p: protocol submitting the update
586 * @src: protocol originating the update
587 * @new: a &rte representing the new route or %NULL for route removal.
588 *
589 * This function is called by the routing protocols whenever they discover
590 * a new route or wish to update/remove an existing route. The right announcement
591 * sequence is to build route attributes first (either un-cached with @aflags set
592 * to zero or a cached one using rta_lookup(); in this case please note that
593 * you need to increase the use count of the attributes yourself by calling
594 * rta_clone()), call rte_get_temp() to obtain a temporary &rte, fill in all
595 * the appropriate data and finally submit the new &rte by calling rte_update().
596 *
597 * @src specifies the protocol that originally created the route and the meaning
598 * of protocol-dependent data of @new. If @new is not %NULL, @src have to be the
599 * same value as @new->attrs->proto. @p specifies the protocol that called
600 * rte_update(). In most cases it is the same protocol as @src. rte_update()
601 * stores @p in @new->sender;
602 *
603 * When rte_update() gets any route, it automatically validates it (checks,
604 * whether the network and next hop address are valid IP addresses and also
605 * whether a normal routing protocol doesn't try to smuggle a host or link
606 * scope route to the table), converts all protocol dependent attributes stored
607 * in the &rte to temporary extended attributes, consults import filters of the
608 * protocol to see if the route should be accepted and/or its attributes modified,
609 * stores the temporary attributes back to the &rte.
610 *
611 * Now, having a "public" version of the route, we
612 * automatically find any old route defined by the protocol @src
613 * for network @n, replace it by the new one (or removing it if @new is %NULL),
614 * recalculate the optimal route for this destination and finally broadcast
615 * the change (if any) to all routing protocols by calling rte_announce().
616 *
617 * All memory used for attribute lists and other temporary allocations is taken
618 * from a special linear pool @rte_update_pool and freed when rte_update()
619 * finishes.
620 */
621
622 void
623 rte_update(rtable *table, net *net, struct proto *p, struct proto *src, rte *new)
624 {
625 ea_list *tmpa = NULL;
626 struct proto_stats *stats = &p->stats;
627
628 #ifdef CONFIG_PIPE
629 if (proto_is_pipe(p) && (p->table == table))
630 stats = pipe_get_peer_stats(p);
631 #endif
632
633 rte_update_lock();
634 if (new)
635 {
636 new->sender = p;
637 struct filter *filter = p->in_filter;
638
639 /* Do not filter routes going through the pipe,
640 they are filtered in the export filter only. */
641 #ifdef CONFIG_PIPE
642 if (proto_is_pipe(p))
643 filter = FILTER_ACCEPT;
644 #endif
645
646 stats->imp_updates_received++;
647 if (!rte_validate(new))
648 {
649 rte_trace_in(D_FILTERS, p, new, "invalid");
650 stats->imp_updates_invalid++;
651 goto drop;
652 }
653 if (filter == FILTER_REJECT)
654 {
655 stats->imp_updates_filtered++;
656 rte_trace_in(D_FILTERS, p, new, "filtered out");
657 goto drop;
658 }
659 if (src->make_tmp_attrs)
660 tmpa = src->make_tmp_attrs(new, rte_update_pool);
661 if (filter)
662 {
663 ea_list *old_tmpa = tmpa;
664 int fr = f_run(filter, &new, &tmpa, rte_update_pool, 0);
665 if (fr > F_ACCEPT)
666 {
667 stats->imp_updates_filtered++;
668 rte_trace_in(D_FILTERS, p, new, "filtered out");
669 goto drop;
670 }
671 if (tmpa != old_tmpa && src->store_tmp_attrs)
672 src->store_tmp_attrs(new, tmpa);
673 }
674 if (!(new->attrs->aflags & RTAF_CACHED)) /* Need to copy attributes */
675 new->attrs = rta_lookup(new->attrs);
676 new->flags |= REF_COW;
677 }
678 else
679 stats->imp_withdraws_received++;
680
681 rte_recalculate(table, net, p, src, new, tmpa);
682 rte_update_unlock();
683 return;
684
685 drop:
686 rte_free(new);
687 rte_recalculate(table, net, p, src, NULL, NULL);
688 rte_update_unlock();
689 }
690
691 void
692 rte_discard(rtable *t, rte *old) /* Non-filtered route deletion, used during garbage collection */
693 {
694 rte_update_lock();
695 rte_recalculate(t, old->net, old->sender, old->attrs->proto, NULL, NULL);
696 rte_update_unlock();
697 }
698
699 /**
700 * rte_dump - dump a route
701 * @e: &rte to be dumped
702 *
703 * This functions dumps contents of a &rte to debug output.
704 */
705 void
706 rte_dump(rte *e)
707 {
708 net *n = e->net;
709 if (n)
710 debug("%-1I/%2d ", n->n.prefix, n->n.pxlen);
711 else
712 debug("??? ");
713 debug("KF=%02x PF=%02x pref=%d lm=%d ", n->n.flags, e->pflags, e->pref, now-e->lastmod);
714 rta_dump(e->attrs);
715 if (e->attrs->proto->proto->dump_attrs)
716 e->attrs->proto->proto->dump_attrs(e);
717 debug("\n");
718 }
719
720 /**
721 * rt_dump - dump a routing table
722 * @t: routing table to be dumped
723 *
724 * This function dumps contents of a given routing table to debug output.
725 */
726 void
727 rt_dump(rtable *t)
728 {
729 rte *e;
730 net *n;
731 struct announce_hook *a;
732
733 debug("Dump of routing table <%s>\n", t->name);
734 #ifdef DEBUGGING
735 fib_check(&t->fib);
736 #endif
737 FIB_WALK(&t->fib, fn)
738 {
739 n = (net *) fn;
740 for(e=n->routes; e; e=e->next)
741 rte_dump(e);
742 }
743 FIB_WALK_END;
744 WALK_LIST(a, t->hooks)
745 debug("\tAnnounces routes to protocol %s\n", a->proto->name);
746 debug("\n");
747 }
748
749 /**
750 * rt_dump_all - dump all routing tables
751 *
752 * This function dumps contents of all routing tables to debug output.
753 */
754 void
755 rt_dump_all(void)
756 {
757 rtable *t;
758
759 WALK_LIST(t, routing_tables)
760 rt_dump(t);
761 }
762
763 static void
764 rt_gc(void *tab)
765 {
766 rtable *t = tab;
767
768 DBG("Entered routing table garbage collector for %s after %d seconds and %d deletes\n",
769 t->name, (int)(now - t->gc_time), t->gc_counter);
770 rt_prune(t);
771 }
772
773 void
774 rt_setup(pool *p, rtable *t, char *name, struct rtable_config *cf)
775 {
776 bzero(t, sizeof(*t));
777 fib_init(&t->fib, p, sizeof(net), 0, rte_init);
778 t->name = name;
779 t->config = cf;
780 init_list(&t->hooks);
781 if (cf)
782 {
783 t->gc_event = ev_new(p);
784 t->gc_event->hook = rt_gc;
785 t->gc_event->data = t;
786 t->gc_time = now;
787 }
788 }
789
790 /**
791 * rt_init - initialize routing tables
792 *
793 * This function is called during BIRD startup. It initializes the
794 * routing table module.
795 */
796 void
797 rt_init(void)
798 {
799 rta_init();
800 rt_table_pool = rp_new(&root_pool, "Routing tables");
801 rte_update_pool = lp_new(rt_table_pool, 4080);
802 rte_slab = sl_new(rt_table_pool, sizeof(rte));
803 init_list(&routing_tables);
804 }
805
806 /**
807 * rt_prune - prune a routing table
808 * @tab: routing table to be pruned
809 *
810 * This function is called whenever a protocol shuts down. It scans
811 * the routing table and removes all routes belonging to inactive
812 * protocols and also stale network entries.
813 */
814 void
815 rt_prune(rtable *tab)
816 {
817 struct fib_iterator fit;
818 int rcnt = 0, rdel = 0, ncnt = 0, ndel = 0;
819
820 DBG("Pruning route table %s\n", tab->name);
821 #ifdef DEBUGGING
822 fib_check(&tab->fib);
823 #endif
824 FIB_ITERATE_INIT(&fit, &tab->fib);
825 again:
826 FIB_ITERATE_START(&tab->fib, &fit, f)
827 {
828 net *n = (net *) f;
829 rte *e;
830 ncnt++;
831 rescan:
832 for (e=n->routes; e; e=e->next, rcnt++)
833 if (e->sender->core_state != FS_HAPPY &&
834 e->sender->core_state != FS_FEEDING)
835 {
836 rte_discard(tab, e);
837 rdel++;
838 goto rescan;
839 }
840 if (!n->routes) /* Orphaned FIB entry? */
841 {
842 FIB_ITERATE_PUT(&fit, f);
843 fib_delete(&tab->fib, f);
844 ndel++;
845 goto again;
846 }
847 }
848 FIB_ITERATE_END(f);
849 DBG("Pruned %d of %d routes and %d of %d networks\n", rdel, rcnt, ndel, ncnt);
850 #ifdef DEBUGGING
851 fib_check(&tab->fib);
852 #endif
853 tab->gc_counter = 0;
854 tab->gc_time = now;
855 }
856
857 /**
858 * rt_prune_all - prune all routing tables
859 *
860 * This function calls rt_prune() for all known routing tables.
861 */
862 void
863 rt_prune_all(void)
864 {
865 rtable *t;
866
867 WALK_LIST(t, routing_tables)
868 rt_prune(t);
869 }
870
871 struct rtable_config *
872 rt_new_table(struct symbol *s)
873 {
874 struct rtable_config *c = cfg_allocz(sizeof(struct rtable_config));
875
876 cf_define_symbol(s, SYM_TABLE, c);
877 c->name = s->name;
878 add_tail(&new_config->tables, &c->n);
879 c->gc_max_ops = 1000;
880 c->gc_min_time = 5;
881 return c;
882 }
883
884 void
885 rt_preconfig(struct config *c)
886 {
887 struct symbol *s = cf_find_symbol("master");
888
889 init_list(&c->tables);
890 c->master_rtc = rt_new_table(s);
891 }
892
893 /**
894 * rt_lock_table - lock a routing table
895 * @r: routing table to be locked
896 *
897 * Lock a routing table, because it's in use by a protocol,
898 * preventing it from being freed when it gets undefined in a new
899 * configuration.
900 */
901 void
902 rt_lock_table(rtable *r)
903 {
904 r->use_count++;
905 }
906
907 /**
908 * rt_unlock_table - unlock a routing table
909 * @r: routing table to be unlocked
910 *
911 * Unlock a routing table formerly locked by rt_lock_table(),
912 * that is decrease its use count and delete it if it's scheduled
913 * for deletion by configuration changes.
914 */
915 void
916 rt_unlock_table(rtable *r)
917 {
918 if (!--r->use_count && r->deleted)
919 {
920 struct config *conf = r->deleted;
921 DBG("Deleting routing table %s\n", r->name);
922 rem_node(&r->n);
923 fib_free(&r->fib);
924 mb_free(r);
925 config_del_obstacle(conf);
926 }
927 }
928
929 /**
930 * rt_commit - commit new routing table configuration
931 * @new: new configuration
932 * @old: original configuration or %NULL if it's boot time config
933 *
934 * Scan differences between @old and @new configuration and modify
935 * the routing tables according to these changes. If @new defines a
936 * previously unknown table, create it, if it omits a table existing
937 * in @old, schedule it for deletion (it gets deleted when all protocols
938 * disconnect from it by calling rt_unlock_table()), if it exists
939 * in both configurations, leave it unchanged.
940 */
941 void
942 rt_commit(struct config *new, struct config *old)
943 {
944 struct rtable_config *o, *r;
945
946 DBG("rt_commit:\n");
947 if (old)
948 {
949 WALK_LIST(o, old->tables)
950 {
951 rtable *ot = o->table;
952 if (!ot->deleted)
953 {
954 struct symbol *sym = cf_find_symbol(o->name);
955 if (sym && sym->class == SYM_TABLE && !new->shutdown)
956 {
957 DBG("\t%s: same\n", o->name);
958 r = sym->def;
959 r->table = ot;
960 ot->name = r->name;
961 ot->config = r;
962 }
963 else
964 {
965 DBG("\t%s: deleted\n", o->name);
966 ot->deleted = old;
967 config_add_obstacle(old);
968 rt_lock_table(ot);
969 rt_unlock_table(ot);
970 }
971 }
972 }
973 }
974
975 WALK_LIST(r, new->tables)
976 if (!r->table)
977 {
978 rtable *t = mb_alloc(rt_table_pool, sizeof(struct rtable));
979 DBG("\t%s: created\n", r->name);
980 rt_setup(rt_table_pool, t, r->name, r);
981 add_tail(&routing_tables, &t->n);
982 r->table = t;
983 }
984 DBG("\tdone\n");
985 }
986
987 static inline void
988 do_feed_baby(struct proto *p, int type, struct announce_hook *h, net *n, rte *e)
989 {
990 struct proto *q = e->attrs->proto;
991 ea_list *tmpa;
992
993 rte_update_lock();
994 tmpa = q->make_tmp_attrs ? q->make_tmp_attrs(e, rte_update_pool) : NULL;
995 do_rte_announce(h, type, n, e, p->refeeding ? e : NULL, tmpa, p->refeeding);
996 rte_update_unlock();
997 }
998
999 /**
1000 * rt_feed_baby - advertise routes to a new protocol
1001 * @p: protocol to be fed
1002 *
1003 * This function performs one pass of advertisement of routes to a newly
1004 * initialized protocol. It's called by the protocol code as long as it
1005 * has something to do. (We avoid transferring all the routes in single
1006 * pass in order not to monopolize CPU time.)
1007 */
1008 int
1009 rt_feed_baby(struct proto *p)
1010 {
1011 struct announce_hook *h;
1012 struct fib_iterator *fit;
1013 int max_feed = 256;
1014
1015 if (!p->feed_ahook) /* Need to initialize first */
1016 {
1017 if (!p->ahooks)
1018 return 1;
1019 DBG("Announcing routes to new protocol %s\n", p->name);
1020 p->feed_ahook = p->ahooks;
1021 fit = p->feed_iterator = mb_alloc(p->pool, sizeof(struct fib_iterator));
1022 goto next_hook;
1023 }
1024 fit = p->feed_iterator;
1025
1026 again:
1027 h = p->feed_ahook;
1028 FIB_ITERATE_START(&h->table->fib, fit, fn)
1029 {
1030 net *n = (net *) fn;
1031 rte *e = n->routes;
1032 if (max_feed <= 0)
1033 {
1034 FIB_ITERATE_PUT(fit, fn);
1035 return 0;
1036 }
1037
1038 if (p->accept_ra_types == RA_OPTIMAL)
1039 if (e)
1040 {
1041 if (p->core_state != FS_FEEDING)
1042 return 1; /* In the meantime, the protocol fell down. */
1043 do_feed_baby(p, RA_OPTIMAL, h, n, e);
1044 max_feed--;
1045 }
1046
1047 if (p->accept_ra_types == RA_ANY)
1048 for(e = n->routes; e != NULL; e = e->next)
1049 {
1050 if (p->core_state != FS_FEEDING)
1051 return 1; /* In the meantime, the protocol fell down. */
1052 do_feed_baby(p, RA_ANY, h, n, e);
1053 max_feed--;
1054 }
1055 }
1056 FIB_ITERATE_END(fn);
1057 p->feed_ahook = h->next;
1058 if (!p->feed_ahook)
1059 {
1060 mb_free(p->feed_iterator);
1061 p->feed_iterator = NULL;
1062 return 1;
1063 }
1064
1065 next_hook:
1066 h = p->feed_ahook;
1067 FIB_ITERATE_INIT(fit, &h->table->fib);
1068 goto again;
1069 }
1070
1071 /**
1072 * rt_feed_baby_abort - abort protocol feeding
1073 * @p: protocol
1074 *
1075 * This function is called by the protocol code when the protocol
1076 * stops or ceases to exist before the last iteration of rt_feed_baby()
1077 * has finished.
1078 */
1079 void
1080 rt_feed_baby_abort(struct proto *p)
1081 {
1082 if (p->feed_ahook)
1083 {
1084 /* Unlink the iterator and exit */
1085 fit_get(&p->feed_ahook->table->fib, p->feed_iterator);
1086 p->feed_ahook = NULL;
1087 }
1088 }
1089
1090 /*
1091 * CLI commands
1092 */
1093
1094 static void
1095 rt_format_via(rte *e, byte *via)
1096 {
1097 rta *a = e->attrs;
1098
1099 switch (a->dest)
1100 {
1101 case RTD_ROUTER: bsprintf(via, "via %I on %s", a->gw, a->iface->name); break;
1102 case RTD_DEVICE: bsprintf(via, "dev %s", a->iface->name); break;
1103 case RTD_BLACKHOLE: bsprintf(via, "blackhole"); break;
1104 case RTD_UNREACHABLE: bsprintf(via, "unreachable"); break;
1105 case RTD_PROHIBIT: bsprintf(via, "prohibited"); break;
1106 default: bsprintf(via, "???");
1107 }
1108 }
1109
1110 static void
1111 rt_show_rte(struct cli *c, byte *ia, rte *e, struct rt_show_data *d, ea_list *tmpa)
1112 {
1113 byte via[STD_ADDRESS_P_LENGTH+32], from[STD_ADDRESS_P_LENGTH+6];
1114 byte tm[TM_DATETIME_BUFFER_SIZE], info[256];
1115 rta *a = e->attrs;
1116 int primary = (e->net->routes == e);
1117
1118 rt_format_via(e, via);
1119 tm_format_datetime(tm, &config->tf_route, e->lastmod);
1120 if (ipa_nonzero(a->from) && !ipa_equal(a->from, a->gw))
1121 bsprintf(from, " from %I", a->from);
1122 else
1123 from[0] = 0;
1124 if (a->proto->proto->get_route_info || d->verbose)
1125 {
1126 /* Need to normalize the extended attributes */
1127 ea_list *t = tmpa;
1128 t = ea_append(t, a->eattrs);
1129 tmpa = alloca(ea_scan(t));
1130 ea_merge(t, tmpa);
1131 ea_sort(tmpa);
1132 }
1133 if (a->proto->proto->get_route_info)
1134 a->proto->proto->get_route_info(e, info, tmpa);
1135 else
1136 bsprintf(info, " (%d)", e->pref);
1137 cli_printf(c, -1007, "%-18s %s [%s %s%s]%s%s", ia, via, a->proto->name,
1138 tm, from, primary ? " *" : "", info);
1139 if (d->verbose)
1140 rta_show(c, a, tmpa);
1141 }
1142
1143 static void
1144 rt_show_net(struct cli *c, net *n, struct rt_show_data *d)
1145 {
1146 rte *e, *ee;
1147 byte ia[STD_ADDRESS_P_LENGTH+8];
1148 int ok;
1149
1150 bsprintf(ia, "%I/%d", n->n.prefix, n->n.pxlen);
1151 if (n->routes)
1152 d->net_counter++;
1153 for(e=n->routes; e; e=e->next)
1154 {
1155 struct ea_list *tmpa, *old_tmpa;
1156 struct proto *p0 = e->attrs->proto;
1157 struct proto *p1 = d->export_protocol;
1158 struct proto *p2 = d->show_protocol;
1159 d->rt_counter++;
1160 ee = e;
1161 rte_update_lock(); /* We use the update buffer for filtering */
1162 old_tmpa = tmpa = p0->make_tmp_attrs ? p0->make_tmp_attrs(e, rte_update_pool) : NULL;
1163 ok = (d->filter == FILTER_ACCEPT || f_run(d->filter, &e, &tmpa, rte_update_pool, FF_FORCE_TMPATTR) <= F_ACCEPT);
1164 if (p2 && p2 != p0) ok = 0;
1165 if (ok && d->export_mode)
1166 {
1167 int ic;
1168 if ((ic = p1->import_control ? p1->import_control(p1, &e, &tmpa, rte_update_pool) : 0) < 0)
1169 ok = 0;
1170 else if (!ic && d->export_mode > 1)
1171 {
1172 /* FIXME - this shows what should be exported according
1173 to current filters, but not what was really exported.
1174 'configure soft' command may change the export filter
1175 and do not update routes */
1176
1177 if ((p1->out_filter == FILTER_REJECT) ||
1178 (p1->out_filter && f_run(p1->out_filter, &e, &tmpa, rte_update_pool, FF_FORCE_TMPATTR) > F_ACCEPT))
1179 ok = 0;
1180 }
1181 }
1182 if (ok)
1183 {
1184 d->show_counter++;
1185 if (d->stats < 2)
1186 rt_show_rte(c, ia, e, d, tmpa);
1187 ia[0] = 0;
1188 }
1189 if (e != ee)
1190 rte_free(ee);
1191 rte_update_unlock();
1192 if (d->primary_only)
1193 break;
1194 }
1195 }
1196
1197 static void
1198 rt_show_cont(struct cli *c)
1199 {
1200 struct rt_show_data *d = c->rover;
1201 #ifdef DEBUGGING
1202 unsigned max = 4;
1203 #else
1204 unsigned max = 64;
1205 #endif
1206 struct fib *fib = &d->table->fib;
1207 struct fib_iterator *it = &d->fit;
1208
1209 FIB_ITERATE_START(fib, it, f)
1210 {
1211 net *n = (net *) f;
1212 if (d->running_on_config && d->running_on_config != config)
1213 {
1214 cli_printf(c, 8004, "Stopped due to reconfiguration");
1215 goto done;
1216 }
1217 if (d->export_protocol &&
1218 d->export_protocol->core_state != FS_HAPPY &&
1219 d->export_protocol->core_state != FS_FEEDING)
1220 {
1221 cli_printf(c, 8005, "Protocol is down");
1222 goto done;
1223 }
1224 if (!max--)
1225 {
1226 FIB_ITERATE_PUT(it, f);
1227 return;
1228 }
1229 rt_show_net(c, n, d);
1230 }
1231 FIB_ITERATE_END(f);
1232 if (d->stats)
1233 cli_printf(c, 14, "%d of %d routes for %d networks", d->show_counter, d->rt_counter, d->net_counter);
1234 else
1235 cli_printf(c, 0, "");
1236 done:
1237 c->cont = c->cleanup = NULL;
1238 }
1239
1240 static void
1241 rt_show_cleanup(struct cli *c)
1242 {
1243 struct rt_show_data *d = c->rover;
1244
1245 /* Unlink the iterator */
1246 fit_get(&d->table->fib, &d->fit);
1247 }
1248
1249 void
1250 rt_show(struct rt_show_data *d)
1251 {
1252 net *n;
1253
1254 if (d->pxlen == 256)
1255 {
1256 FIB_ITERATE_INIT(&d->fit, &d->table->fib);
1257 this_cli->cont = rt_show_cont;
1258 this_cli->cleanup = rt_show_cleanup;
1259 this_cli->rover = d;
1260 }
1261 else
1262 {
1263 if (d->show_for)
1264 n = fib_route(&d->table->fib, d->prefix, d->pxlen);
1265 else
1266 n = fib_find(&d->table->fib, &d->prefix, d->pxlen);
1267 if (n)
1268 {
1269 rt_show_net(this_cli, n, d);
1270 cli_msg(0, "");
1271 }
1272 else
1273 cli_msg(8001, "Network not in table");
1274 }
1275 }
1276
1277 /*
1278 * Documentation for functions declared inline in route.h
1279 */
1280 #if 0
1281
1282 /**
1283 * net_find - find a network entry
1284 * @tab: a routing table
1285 * @addr: address of the network
1286 * @len: length of the network prefix
1287 *
1288 * net_find() looks up the given network in routing table @tab and
1289 * returns a pointer to its &net entry or %NULL if no such network
1290 * exists.
1291 */
1292 static inline net *net_find(rtable *tab, ip_addr addr, unsigned len)
1293 { DUMMY; }
1294
1295 /**
1296 * net_get - obtain a network entry
1297 * @tab: a routing table
1298 * @addr: address of the network
1299 * @len: length of the network prefix
1300 *
1301 * net_get() looks up the given network in routing table @tab and
1302 * returns a pointer to its &net entry. If no such entry exists, it's
1303 * created.
1304 */
1305 static inline net *net_get(rtable *tab, ip_addr addr, unsigned len)
1306 { DUMMY; }
1307
1308 /**
1309 * rte_cow - copy a route for writing
1310 * @r: a route entry to be copied
1311 *
1312 * rte_cow() takes a &rte and prepares it for modification. The exact action
1313 * taken depends on the flags of the &rte -- if it's a temporary entry, it's
1314 * just returned unchanged, else a new temporary entry with the same contents
1315 * is created.
1316 *
1317 * The primary use of this function is inside the filter machinery -- when
1318 * a filter wants to modify &rte contents (to change the preference or to
1319 * attach another set of attributes), it must ensure that the &rte is not
1320 * shared with anyone else (and especially that it isn't stored in any routing
1321 * table).
1322 *
1323 * Result: a pointer to the new writable &rte.
1324 */
1325 static inline rte * rte_cow(rte *r)
1326 { DUMMY; }
1327
1328 #endif