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