]> git.ipfire.org Git - thirdparty/bird.git/blob - nest/rt-table.c
Fixes a bug in 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 insead 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=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 (new)
646 {
647 for (k=&net->routes; *k; k=&(*k)->next)
648 if (rte_better(new, *k))
649 break;
650
651 new->lastmod = now;
652 new->next = *k;
653 *k = new;
654
655 rte_trace_in(D_ROUTES, p, new, net->routes == new ? "added [best]" : "added");
656 }
657
658 /* Log the route removal */
659 if (!new && (p->debug & D_ROUTES))
660 {
661 if (old != old_best)
662 rte_trace_in(D_ROUTES, p, old, "removed");
663 else if (net->routes)
664 rte_trace_in(D_ROUTES, p, old, "removed [replaced]");
665 else
666 rte_trace_in(D_ROUTES, p, old, "removed [sole]");
667 }
668
669 rte_announce(table, RA_ANY, net, new, old, NULL, tmpa);
670 rte_announce(table, RA_OPTIMAL, net, net->routes, old_best, NULL, tmpa);
671 rte_announce(table, RA_ACCEPTED, net, new, old, before_old, tmpa);
672
673 if (!net->routes &&
674 (table->gc_counter++ >= table->config->gc_max_ops) &&
675 (table->gc_time + table->config->gc_min_time <= now))
676 rt_schedule_gc(table);
677
678 if (old)
679 {
680 if (p->rte_remove)
681 p->rte_remove(net, old);
682 rte_free_quick(old);
683 }
684 if (new)
685 {
686 if (p->rte_insert)
687 p->rte_insert(net, new);
688 }
689 }
690
691 static int rte_update_nest_cnt; /* Nesting counter to allow recursive updates */
692
693 static inline void
694 rte_update_lock(void)
695 {
696 rte_update_nest_cnt++;
697 }
698
699 static inline void
700 rte_update_unlock(void)
701 {
702 if (!--rte_update_nest_cnt)
703 lp_flush(rte_update_pool);
704 }
705
706 /**
707 * rte_update - enter a new update to a routing table
708 * @table: table to be updated
709 * @ah: pointer to table announce hook
710 * @net: network node
711 * @p: protocol submitting the update
712 * @src: protocol originating the update
713 * @new: a &rte representing the new route or %NULL for route removal.
714 *
715 * This function is called by the routing protocols whenever they discover
716 * a new route or wish to update/remove an existing route. The right announcement
717 * sequence is to build route attributes first (either un-cached with @aflags set
718 * to zero or a cached one using rta_lookup(); in this case please note that
719 * you need to increase the use count of the attributes yourself by calling
720 * rta_clone()), call rte_get_temp() to obtain a temporary &rte, fill in all
721 * the appropriate data and finally submit the new &rte by calling rte_update().
722 *
723 * @src specifies the protocol that originally created the route and the meaning
724 * of protocol-dependent data of @new. If @new is not %NULL, @src have to be the
725 * same value as @new->attrs->proto. @p specifies the protocol that called
726 * rte_update(). In most cases it is the same protocol as @src. rte_update()
727 * stores @p in @new->sender;
728 *
729 * When rte_update() gets any route, it automatically validates it (checks,
730 * whether the network and next hop address are valid IP addresses and also
731 * whether a normal routing protocol doesn't try to smuggle a host or link
732 * scope route to the table), converts all protocol dependent attributes stored
733 * in the &rte to temporary extended attributes, consults import filters of the
734 * protocol to see if the route should be accepted and/or its attributes modified,
735 * stores the temporary attributes back to the &rte.
736 *
737 * Now, having a "public" version of the route, we
738 * automatically find any old route defined by the protocol @src
739 * for network @n, replace it by the new one (or removing it if @new is %NULL),
740 * recalculate the optimal route for this destination and finally broadcast
741 * the change (if any) to all routing protocols by calling rte_announce().
742 *
743 * All memory used for attribute lists and other temporary allocations is taken
744 * from a special linear pool @rte_update_pool and freed when rte_update()
745 * finishes.
746 */
747
748 void
749 rte_update2(struct announce_hook *ah, net *net, rte *new, struct proto *src)
750 {
751 struct proto *p = ah->proto;
752 struct proto_stats *stats = ah->stats;
753 struct filter *filter = ah->in_filter;
754 ea_list *tmpa = NULL;
755
756 rte_update_lock();
757 if (new)
758 {
759 new->sender = ah;
760
761 stats->imp_updates_received++;
762 if (!rte_validate(new))
763 {
764 rte_trace_in(D_FILTERS, p, new, "invalid");
765 stats->imp_updates_invalid++;
766 goto drop;
767 }
768 if (filter == FILTER_REJECT)
769 {
770 stats->imp_updates_filtered++;
771 rte_trace_in(D_FILTERS, p, new, "filtered out");
772 goto drop;
773 }
774 if (src->make_tmp_attrs)
775 tmpa = src->make_tmp_attrs(new, rte_update_pool);
776 if (filter)
777 {
778 ea_list *old_tmpa = tmpa;
779 int fr = f_run(filter, &new, &tmpa, rte_update_pool, 0);
780 if (fr > F_ACCEPT)
781 {
782 stats->imp_updates_filtered++;
783 rte_trace_in(D_FILTERS, p, new, "filtered out");
784 goto drop;
785 }
786 if (tmpa != old_tmpa && src->store_tmp_attrs)
787 src->store_tmp_attrs(new, tmpa);
788 }
789 if (!(new->attrs->aflags & RTAF_CACHED)) /* Need to copy attributes */
790 new->attrs = rta_lookup(new->attrs);
791 new->flags |= REF_COW;
792 }
793 else
794 stats->imp_withdraws_received++;
795
796 rte_recalculate(ah, net, new, tmpa, src);
797 rte_update_unlock();
798 return;
799
800 drop:
801 rte_free(new);
802 rte_recalculate(ah, net, NULL, NULL, src);
803 rte_update_unlock();
804 }
805
806 /* Independent call to rte_announce(), used from next hop
807 recalculation, outside of rte_update(). new must be non-NULL */
808 static inline void
809 rte_announce_i(rtable *tab, unsigned type, net *n, rte *new, rte *old)
810 {
811 struct proto *src;
812 ea_list *tmpa;
813
814 rte_update_lock();
815 src = new->attrs->proto;
816 tmpa = src->make_tmp_attrs ? src->make_tmp_attrs(new, rte_update_pool) : NULL;
817 rte_announce(tab, type, n, new, old, NULL, tmpa);
818 rte_update_unlock();
819 }
820
821 void
822 rte_discard(rtable *t, rte *old) /* Non-filtered route deletion, used during garbage collection */
823 {
824 rte_update_lock();
825 rte_recalculate(old->sender, old->net, NULL, NULL, old->attrs->proto);
826 rte_update_unlock();
827 }
828
829 /**
830 * rte_dump - dump a route
831 * @e: &rte to be dumped
832 *
833 * This functions dumps contents of a &rte to debug output.
834 */
835 void
836 rte_dump(rte *e)
837 {
838 net *n = e->net;
839 if (n)
840 debug("%-1I/%2d ", n->n.prefix, n->n.pxlen);
841 else
842 debug("??? ");
843 debug("KF=%02x PF=%02x pref=%d lm=%d ", n->n.flags, e->pflags, e->pref, now-e->lastmod);
844 rta_dump(e->attrs);
845 if (e->attrs->proto->proto->dump_attrs)
846 e->attrs->proto->proto->dump_attrs(e);
847 debug("\n");
848 }
849
850 /**
851 * rt_dump - dump a routing table
852 * @t: routing table to be dumped
853 *
854 * This function dumps contents of a given routing table to debug output.
855 */
856 void
857 rt_dump(rtable *t)
858 {
859 rte *e;
860 net *n;
861 struct announce_hook *a;
862
863 debug("Dump of routing table <%s>\n", t->name);
864 #ifdef DEBUGGING
865 fib_check(&t->fib);
866 #endif
867 FIB_WALK(&t->fib, fn)
868 {
869 n = (net *) fn;
870 for(e=n->routes; e; e=e->next)
871 rte_dump(e);
872 }
873 FIB_WALK_END;
874 WALK_LIST(a, t->hooks)
875 debug("\tAnnounces routes to protocol %s\n", a->proto->name);
876 debug("\n");
877 }
878
879 /**
880 * rt_dump_all - dump all routing tables
881 *
882 * This function dumps contents of all routing tables to debug output.
883 */
884 void
885 rt_dump_all(void)
886 {
887 rtable *t;
888
889 WALK_LIST(t, routing_tables)
890 rt_dump(t);
891 }
892
893 static inline void
894 rt_schedule_gc(rtable *tab)
895 {
896 if (tab->gc_scheduled)
897 return;
898
899 tab->gc_scheduled = 1;
900 ev_schedule(tab->rt_event);
901 }
902
903 static inline void
904 rt_schedule_hcu(rtable *tab)
905 {
906 if (tab->hcu_scheduled)
907 return;
908
909 tab->hcu_scheduled = 1;
910 ev_schedule(tab->rt_event);
911 }
912
913 static inline void
914 rt_schedule_nhu(rtable *tab)
915 {
916 if (tab->nhu_state == 0)
917 ev_schedule(tab->rt_event);
918
919 /* state change 0->1, 2->3 */
920 tab->nhu_state |= 1;
921 }
922
923 static void
924 rt_prune_nets(rtable *tab)
925 {
926 struct fib_iterator fit;
927 int ncnt = 0, ndel = 0;
928
929 #ifdef DEBUGGING
930 fib_check(&tab->fib);
931 #endif
932
933 FIB_ITERATE_INIT(&fit, &tab->fib);
934 again:
935 FIB_ITERATE_START(&tab->fib, &fit, f)
936 {
937 net *n = (net *) f;
938 ncnt++;
939 if (!n->routes) /* Orphaned FIB entry */
940 {
941 FIB_ITERATE_PUT(&fit, f);
942 fib_delete(&tab->fib, f);
943 ndel++;
944 goto again;
945 }
946 }
947 FIB_ITERATE_END(f);
948 DBG("Pruned %d of %d networks\n", ndel, ncnt);
949
950 tab->gc_counter = 0;
951 tab->gc_time = now;
952 tab->gc_scheduled = 0;
953 }
954
955 static void
956 rt_event(void *ptr)
957 {
958 rtable *tab = ptr;
959
960 if (tab->hcu_scheduled)
961 rt_update_hostcache(tab);
962
963 if (tab->nhu_state)
964 rt_next_hop_update(tab);
965
966 if (tab->gc_scheduled)
967 rt_prune_nets(tab);
968 }
969
970 void
971 rt_setup(pool *p, rtable *t, char *name, struct rtable_config *cf)
972 {
973 bzero(t, sizeof(*t));
974 fib_init(&t->fib, p, sizeof(net), 0, rte_init);
975 t->name = name;
976 t->config = cf;
977 init_list(&t->hooks);
978 if (cf)
979 {
980 t->rt_event = ev_new(p);
981 t->rt_event->hook = rt_event;
982 t->rt_event->data = t;
983 t->gc_time = now;
984 }
985 }
986
987 /**
988 * rt_init - initialize routing tables
989 *
990 * This function is called during BIRD startup. It initializes the
991 * routing table module.
992 */
993 void
994 rt_init(void)
995 {
996 rta_init();
997 rt_table_pool = rp_new(&root_pool, "Routing tables");
998 rte_update_pool = lp_new(rt_table_pool, 4080);
999 rte_slab = sl_new(rt_table_pool, sizeof(rte));
1000 init_list(&routing_tables);
1001 }
1002
1003
1004 /* Called from proto_schedule_flush_loop() only,
1005 ensuring that all prune states are zero */
1006 void
1007 rt_schedule_prune_all(void)
1008 {
1009 rtable *t;
1010
1011 WALK_LIST(t, routing_tables)
1012 t->prune_state = 1;
1013 }
1014
1015 static inline int
1016 rt_prune_step(rtable *tab, int *max_feed)
1017 {
1018 struct fib_iterator *fit = &tab->prune_fit;
1019
1020 DBG("Pruning route table %s\n", tab->name);
1021 #ifdef DEBUGGING
1022 fib_check(&tab->fib);
1023 #endif
1024
1025 if (tab->prune_state == 0)
1026 return 1;
1027
1028 if (tab->prune_state == 1)
1029 {
1030 FIB_ITERATE_INIT(fit, &tab->fib);
1031 tab->prune_state = 2;
1032 }
1033
1034 again:
1035 FIB_ITERATE_START(&tab->fib, fit, fn)
1036 {
1037 net *n = (net *) fn;
1038 rte *e;
1039
1040 rescan:
1041 for (e=n->routes; e; e=e->next)
1042 if (e->sender->proto->core_state != FS_HAPPY &&
1043 e->sender->proto->core_state != FS_FEEDING)
1044 {
1045 if (*max_feed <= 0)
1046 {
1047 FIB_ITERATE_PUT(fit, fn);
1048 return 0;
1049 }
1050
1051 rte_discard(tab, e);
1052 (*max_feed)--;
1053
1054 goto rescan;
1055 }
1056 if (!n->routes) /* Orphaned FIB entry */
1057 {
1058 FIB_ITERATE_PUT(fit, fn);
1059 fib_delete(&tab->fib, fn);
1060 goto again;
1061 }
1062 }
1063 FIB_ITERATE_END(fn);
1064
1065 #ifdef DEBUGGING
1066 fib_check(&tab->fib);
1067 #endif
1068
1069 tab->prune_state = 0;
1070 return 1;
1071 }
1072
1073 /**
1074 * rt_prune_loop - prune routing tables
1075 * @tab: routing table to be pruned
1076 *
1077 * The prune loop scans routing tables and removes routes belonging to
1078 * inactive protocols and also stale network entries. Returns 1 when
1079 * all such routes are pruned. It is a part of the protocol flushing
1080 * loop.
1081 */
1082 int
1083 rt_prune_loop(void)
1084 {
1085 rtable *t;
1086 int max_feed = 512;
1087
1088 WALK_LIST(t, routing_tables)
1089 if (! rt_prune_step(t, &max_feed))
1090 return 0;
1091
1092 return 1;
1093 }
1094
1095 void
1096 rt_preconfig(struct config *c)
1097 {
1098 struct symbol *s = cf_find_symbol("master");
1099
1100 init_list(&c->tables);
1101 c->master_rtc = rt_new_table(s);
1102 }
1103
1104
1105 /*
1106 * Some functions for handing internal next hop updates
1107 * triggered by rt_schedule_nhu().
1108 */
1109
1110 static inline int
1111 rta_next_hop_outdated(rta *a)
1112 {
1113 struct hostentry *he = a->hostentry;
1114
1115 if (!he)
1116 return 0;
1117
1118 if (!he->src)
1119 return a->dest != RTD_UNREACHABLE;
1120
1121 return (a->iface != he->src->iface) || !ipa_equal(a->gw, he->gw) ||
1122 (a->dest != he->dest) || (a->igp_metric != he->igp_metric) ||
1123 !mpnh_same(a->nexthops, he->src->nexthops);
1124 }
1125
1126 static inline void
1127 rta_apply_hostentry(rta *a, struct hostentry *he)
1128 {
1129 a->hostentry = he;
1130 a->iface = he->src ? he->src->iface : NULL;
1131 a->gw = he->gw;
1132 a->dest = he->dest;
1133 a->igp_metric = he->igp_metric;
1134 a->nexthops = he->src ? he->src->nexthops : NULL;
1135 }
1136
1137 static inline rte *
1138 rt_next_hop_update_rte(rtable *tab, rte *old)
1139 {
1140 rta a;
1141 memcpy(&a, old->attrs, sizeof(rta));
1142 rta_apply_hostentry(&a, old->attrs->hostentry);
1143 a.aflags = 0;
1144
1145 rte *e = sl_alloc(rte_slab);
1146 memcpy(e, old, sizeof(rte));
1147 e->attrs = rta_lookup(&a);
1148
1149 return e;
1150 }
1151
1152 static inline int
1153 rt_next_hop_update_net(rtable *tab, net *n)
1154 {
1155 rte **k, *e, *new, *old_best, **new_best;
1156 int count = 0;
1157 int free_old_best = 0;
1158
1159 old_best = n->routes;
1160 if (!old_best)
1161 return 0;
1162
1163 for (k = &n->routes; e = *k; k = &e->next)
1164 if (rta_next_hop_outdated(e->attrs))
1165 {
1166 new = rt_next_hop_update_rte(tab, e);
1167 *k = new;
1168
1169 rte_announce_i(tab, RA_ANY, n, new, e);
1170 rte_trace_in(D_ROUTES, new->sender->proto, new, "updated");
1171
1172 /* Call a pre-comparison hook */
1173 /* Not really an efficient way to compute this */
1174 if (e->attrs->proto->rte_recalculate)
1175 e->attrs->proto->rte_recalculate(tab, n, new, e, NULL);
1176
1177 if (e != old_best)
1178 rte_free_quick(e);
1179 else /* Freeing of the old best rte is postponed */
1180 free_old_best = 1;
1181
1182 e = new;
1183 count++;
1184 }
1185
1186 if (!count)
1187 return 0;
1188
1189 /* Find the new best route */
1190 new_best = NULL;
1191 for (k = &n->routes; e = *k; k = &e->next)
1192 {
1193 if (!new_best || rte_better(e, *new_best))
1194 new_best = k;
1195 }
1196
1197 /* Relink the new best route to the first position */
1198 new = *new_best;
1199 if (new != n->routes)
1200 {
1201 *new_best = new->next;
1202 new->next = n->routes;
1203 n->routes = new;
1204 }
1205
1206 /* Announce the new best route */
1207 if (new != old_best)
1208 {
1209 rte_announce_i(tab, RA_OPTIMAL, n, new, old_best);
1210 rte_trace_in(D_ROUTES, new->sender->proto, new, "updated [best]");
1211 }
1212
1213 if (free_old_best)
1214 rte_free_quick(old_best);
1215
1216 return count;
1217 }
1218
1219 static void
1220 rt_next_hop_update(rtable *tab)
1221 {
1222 struct fib_iterator *fit = &tab->nhu_fit;
1223 int max_feed = 32;
1224
1225 if (tab->nhu_state == 0)
1226 return;
1227
1228 if (tab->nhu_state == 1)
1229 {
1230 FIB_ITERATE_INIT(fit, &tab->fib);
1231 tab->nhu_state = 2;
1232 }
1233
1234 FIB_ITERATE_START(&tab->fib, fit, fn)
1235 {
1236 if (max_feed <= 0)
1237 {
1238 FIB_ITERATE_PUT(fit, fn);
1239 ev_schedule(tab->rt_event);
1240 return;
1241 }
1242 max_feed -= rt_next_hop_update_net(tab, (net *) fn);
1243 }
1244 FIB_ITERATE_END(fn);
1245
1246 /* state change 2->0, 3->1 */
1247 tab->nhu_state &= 1;
1248
1249 if (tab->nhu_state > 0)
1250 ev_schedule(tab->rt_event);
1251 }
1252
1253
1254 struct rtable_config *
1255 rt_new_table(struct symbol *s)
1256 {
1257 struct rtable_config *c = cfg_allocz(sizeof(struct rtable_config));
1258
1259 cf_define_symbol(s, SYM_TABLE, c);
1260 c->name = s->name;
1261 add_tail(&new_config->tables, &c->n);
1262 c->gc_max_ops = 1000;
1263 c->gc_min_time = 5;
1264 return c;
1265 }
1266
1267 /**
1268 * rt_lock_table - lock a routing table
1269 * @r: routing table to be locked
1270 *
1271 * Lock a routing table, because it's in use by a protocol,
1272 * preventing it from being freed when it gets undefined in a new
1273 * configuration.
1274 */
1275 void
1276 rt_lock_table(rtable *r)
1277 {
1278 r->use_count++;
1279 }
1280
1281 /**
1282 * rt_unlock_table - unlock a routing table
1283 * @r: routing table to be unlocked
1284 *
1285 * Unlock a routing table formerly locked by rt_lock_table(),
1286 * that is decrease its use count and delete it if it's scheduled
1287 * for deletion by configuration changes.
1288 */
1289 void
1290 rt_unlock_table(rtable *r)
1291 {
1292 if (!--r->use_count && r->deleted)
1293 {
1294 struct config *conf = r->deleted;
1295 DBG("Deleting routing table %s\n", r->name);
1296 if (r->hostcache)
1297 rt_free_hostcache(r);
1298 rem_node(&r->n);
1299 fib_free(&r->fib);
1300 rfree(r->rt_event);
1301 mb_free(r);
1302 config_del_obstacle(conf);
1303 }
1304 }
1305
1306 /**
1307 * rt_commit - commit new routing table configuration
1308 * @new: new configuration
1309 * @old: original configuration or %NULL if it's boot time config
1310 *
1311 * Scan differences between @old and @new configuration and modify
1312 * the routing tables according to these changes. If @new defines a
1313 * previously unknown table, create it, if it omits a table existing
1314 * in @old, schedule it for deletion (it gets deleted when all protocols
1315 * disconnect from it by calling rt_unlock_table()), if it exists
1316 * in both configurations, leave it unchanged.
1317 */
1318 void
1319 rt_commit(struct config *new, struct config *old)
1320 {
1321 struct rtable_config *o, *r;
1322
1323 DBG("rt_commit:\n");
1324 if (old)
1325 {
1326 WALK_LIST(o, old->tables)
1327 {
1328 rtable *ot = o->table;
1329 if (!ot->deleted)
1330 {
1331 struct symbol *sym = cf_find_symbol(o->name);
1332 if (sym && sym->class == SYM_TABLE && !new->shutdown)
1333 {
1334 DBG("\t%s: same\n", o->name);
1335 r = sym->def;
1336 r->table = ot;
1337 ot->name = r->name;
1338 ot->config = r;
1339 }
1340 else
1341 {
1342 DBG("\t%s: deleted\n", o->name);
1343 ot->deleted = old;
1344 config_add_obstacle(old);
1345 rt_lock_table(ot);
1346 rt_unlock_table(ot);
1347 }
1348 }
1349 }
1350 }
1351
1352 WALK_LIST(r, new->tables)
1353 if (!r->table)
1354 {
1355 rtable *t = mb_alloc(rt_table_pool, sizeof(struct rtable));
1356 DBG("\t%s: created\n", r->name);
1357 rt_setup(rt_table_pool, t, r->name, r);
1358 add_tail(&routing_tables, &t->n);
1359 r->table = t;
1360 }
1361 DBG("\tdone\n");
1362 }
1363
1364 static inline void
1365 do_feed_baby(struct proto *p, int type, struct announce_hook *h, net *n, rte *e)
1366 {
1367 struct proto *src = e->attrs->proto;
1368 ea_list *tmpa;
1369
1370 rte_update_lock();
1371 tmpa = src->make_tmp_attrs ? src->make_tmp_attrs(e, rte_update_pool) : NULL;
1372 if (type == RA_ACCEPTED)
1373 rt_notify_accepted(h, n, e, NULL, NULL, tmpa, p->refeeding ? 2 : 1);
1374 else
1375 rt_notify_basic(h, n, e, p->refeeding ? e : NULL, tmpa, p->refeeding);
1376 rte_update_unlock();
1377 }
1378
1379 /**
1380 * rt_feed_baby - advertise routes to a new protocol
1381 * @p: protocol to be fed
1382 *
1383 * This function performs one pass of advertisement of routes to a newly
1384 * initialized protocol. It's called by the protocol code as long as it
1385 * has something to do. (We avoid transferring all the routes in single
1386 * pass in order not to monopolize CPU time.)
1387 */
1388 int
1389 rt_feed_baby(struct proto *p)
1390 {
1391 struct announce_hook *h;
1392 struct fib_iterator *fit;
1393 int max_feed = 256;
1394
1395 if (!p->feed_ahook) /* Need to initialize first */
1396 {
1397 if (!p->ahooks)
1398 return 1;
1399 DBG("Announcing routes to new protocol %s\n", p->name);
1400 p->feed_ahook = p->ahooks;
1401 fit = p->feed_iterator = mb_alloc(p->pool, sizeof(struct fib_iterator));
1402 goto next_hook;
1403 }
1404 fit = p->feed_iterator;
1405
1406 again:
1407 h = p->feed_ahook;
1408 FIB_ITERATE_START(&h->table->fib, fit, fn)
1409 {
1410 net *n = (net *) fn;
1411 rte *e = n->routes;
1412 if (max_feed <= 0)
1413 {
1414 FIB_ITERATE_PUT(fit, fn);
1415 return 0;
1416 }
1417
1418 if ((p->accept_ra_types == RA_OPTIMAL) ||
1419 (p->accept_ra_types == RA_ACCEPTED))
1420 if (e)
1421 {
1422 if (p->core_state != FS_FEEDING)
1423 return 1; /* In the meantime, the protocol fell down. */
1424 do_feed_baby(p, p->accept_ra_types, h, n, e);
1425 max_feed--;
1426 }
1427
1428 if (p->accept_ra_types == RA_ANY)
1429 for(e = n->routes; e != NULL; e = e->next)
1430 {
1431 if (p->core_state != FS_FEEDING)
1432 return 1; /* In the meantime, the protocol fell down. */
1433 do_feed_baby(p, RA_ANY, h, n, e);
1434 max_feed--;
1435 }
1436 }
1437 FIB_ITERATE_END(fn);
1438 p->feed_ahook = h->next;
1439 if (!p->feed_ahook)
1440 {
1441 mb_free(p->feed_iterator);
1442 p->feed_iterator = NULL;
1443 return 1;
1444 }
1445
1446 next_hook:
1447 h = p->feed_ahook;
1448 FIB_ITERATE_INIT(fit, &h->table->fib);
1449 goto again;
1450 }
1451
1452 /**
1453 * rt_feed_baby_abort - abort protocol feeding
1454 * @p: protocol
1455 *
1456 * This function is called by the protocol code when the protocol
1457 * stops or ceases to exist before the last iteration of rt_feed_baby()
1458 * has finished.
1459 */
1460 void
1461 rt_feed_baby_abort(struct proto *p)
1462 {
1463 if (p->feed_ahook)
1464 {
1465 /* Unlink the iterator and exit */
1466 fit_get(&p->feed_ahook->table->fib, p->feed_iterator);
1467 p->feed_ahook = NULL;
1468 }
1469 }
1470
1471
1472 static inline unsigned
1473 ptr_hash(void *ptr)
1474 {
1475 uintptr_t p = (uintptr_t) ptr;
1476 return p ^ (p << 8) ^ (p >> 16);
1477 }
1478
1479 static inline unsigned
1480 hc_hash(ip_addr a, rtable *dep)
1481 {
1482 return (ipa_hash(a) ^ ptr_hash(dep)) & 0xffff;
1483 }
1484
1485 static inline void
1486 hc_insert(struct hostcache *hc, struct hostentry *he)
1487 {
1488 unsigned int k = he->hash_key >> hc->hash_shift;
1489 he->next = hc->hash_table[k];
1490 hc->hash_table[k] = he;
1491 }
1492
1493 static inline void
1494 hc_remove(struct hostcache *hc, struct hostentry *he)
1495 {
1496 struct hostentry **hep;
1497 unsigned int k = he->hash_key >> hc->hash_shift;
1498
1499 for (hep = &hc->hash_table[k]; *hep != he; hep = &(*hep)->next);
1500 *hep = he->next;
1501 }
1502
1503 #define HC_DEF_ORDER 10
1504 #define HC_HI_MARK *4
1505 #define HC_HI_STEP 2
1506 #define HC_HI_ORDER 16 /* Must be at most 16 */
1507 #define HC_LO_MARK /5
1508 #define HC_LO_STEP 2
1509 #define HC_LO_ORDER 10
1510
1511 static void
1512 hc_alloc_table(struct hostcache *hc, unsigned order)
1513 {
1514 unsigned hsize = 1 << order;
1515 hc->hash_order = order;
1516 hc->hash_shift = 16 - order;
1517 hc->hash_max = (order >= HC_HI_ORDER) ? ~0 : (hsize HC_HI_MARK);
1518 hc->hash_min = (order <= HC_LO_ORDER) ? 0 : (hsize HC_LO_MARK);
1519
1520 hc->hash_table = mb_allocz(rt_table_pool, hsize * sizeof(struct hostentry *));
1521 }
1522
1523 static void
1524 hc_resize(struct hostcache *hc, unsigned new_order)
1525 {
1526 unsigned old_size = 1 << hc->hash_order;
1527 struct hostentry **old_table = hc->hash_table;
1528 struct hostentry *he, *hen;
1529 int i;
1530
1531 hc_alloc_table(hc, new_order);
1532 for (i = 0; i < old_size; i++)
1533 for (he = old_table[i]; he != NULL; he=hen)
1534 {
1535 hen = he->next;
1536 hc_insert(hc, he);
1537 }
1538 mb_free(old_table);
1539 }
1540
1541 static struct hostentry *
1542 hc_new_hostentry(struct hostcache *hc, ip_addr a, ip_addr ll, rtable *dep, unsigned k)
1543 {
1544 struct hostentry *he = sl_alloc(hc->slab);
1545
1546 he->addr = a;
1547 he->link = ll;
1548 he->tab = dep;
1549 he->hash_key = k;
1550 he->uc = 0;
1551 he->src = NULL;
1552
1553 add_tail(&hc->hostentries, &he->ln);
1554 hc_insert(hc, he);
1555
1556 hc->hash_items++;
1557 if (hc->hash_items > hc->hash_max)
1558 hc_resize(hc, hc->hash_order + HC_HI_STEP);
1559
1560 return he;
1561 }
1562
1563 static void
1564 hc_delete_hostentry(struct hostcache *hc, struct hostentry *he)
1565 {
1566 rta_free(he->src);
1567
1568 rem_node(&he->ln);
1569 hc_remove(hc, he);
1570 sl_free(hc->slab, he);
1571
1572 hc->hash_items--;
1573 if (hc->hash_items < hc->hash_min)
1574 hc_resize(hc, hc->hash_order - HC_LO_STEP);
1575 }
1576
1577 static void
1578 rt_init_hostcache(rtable *tab)
1579 {
1580 struct hostcache *hc = mb_allocz(rt_table_pool, sizeof(struct hostcache));
1581 init_list(&hc->hostentries);
1582
1583 hc->hash_items = 0;
1584 hc_alloc_table(hc, HC_DEF_ORDER);
1585 hc->slab = sl_new(rt_table_pool, sizeof(struct hostentry));
1586
1587 hc->lp = lp_new(rt_table_pool, 1008);
1588 hc->trie = f_new_trie(hc->lp);
1589
1590 tab->hostcache = hc;
1591 }
1592
1593 static void
1594 rt_free_hostcache(rtable *tab)
1595 {
1596 struct hostcache *hc = tab->hostcache;
1597
1598 node *n;
1599 WALK_LIST(n, hc->hostentries)
1600 {
1601 struct hostentry *he = SKIP_BACK(struct hostentry, ln, n);
1602 rta_free(he->src);
1603
1604 if (he->uc)
1605 log(L_ERR "Hostcache is not empty in table %s", tab->name);
1606 }
1607
1608 rfree(hc->slab);
1609 rfree(hc->lp);
1610 mb_free(hc->hash_table);
1611 mb_free(hc);
1612 }
1613
1614 static void
1615 rt_notify_hostcache(rtable *tab, net *net)
1616 {
1617 struct hostcache *hc = tab->hostcache;
1618
1619 if (tab->hcu_scheduled)
1620 return;
1621
1622 if (trie_match_prefix(hc->trie, net->n.prefix, net->n.pxlen))
1623 rt_schedule_hcu(tab);
1624 }
1625
1626 static int
1627 if_local_addr(ip_addr a, struct iface *i)
1628 {
1629 struct ifa *b;
1630
1631 WALK_LIST(b, i->addrs)
1632 if (ipa_equal(a, b->ip))
1633 return 1;
1634
1635 return 0;
1636 }
1637
1638 static u32
1639 rt_get_igp_metric(rte *rt)
1640 {
1641 eattr *ea = ea_find(rt->attrs->eattrs, EA_GEN_IGP_METRIC);
1642
1643 if (ea)
1644 return ea->u.data;
1645
1646 rta *a = rt->attrs;
1647
1648 #ifdef CONFIG_OSPF
1649 if ((a->source == RTS_OSPF) ||
1650 (a->source == RTS_OSPF_IA) ||
1651 (a->source == RTS_OSPF_EXT1))
1652 return rt->u.ospf.metric1;
1653 #endif
1654
1655 #ifdef CONFIG_RIP
1656 if (a->source == RTS_RIP)
1657 return rt->u.rip.metric;
1658 #endif
1659
1660 /* Device routes */
1661 if ((a->dest != RTD_ROUTER) && (a->dest != RTD_MULTIPATH))
1662 return 0;
1663
1664 return IGP_METRIC_UNKNOWN;
1665 }
1666
1667 static int
1668 rt_update_hostentry(rtable *tab, struct hostentry *he)
1669 {
1670 rta *old_src = he->src;
1671 int pxlen = 0;
1672
1673 /* Reset the hostentry */
1674 he->src = NULL;
1675 he->gw = IPA_NONE;
1676 he->dest = RTD_UNREACHABLE;
1677 he->igp_metric = 0;
1678
1679 net *n = net_route(tab, he->addr, MAX_PREFIX_LENGTH);
1680 if (n)
1681 {
1682 rta *a = n->routes->attrs;
1683 pxlen = n->n.pxlen;
1684
1685 if (a->hostentry)
1686 {
1687 /* Recursive route should not depend on another recursive route */
1688 log(L_WARN "Next hop address %I resolvable through recursive route for %I/%d",
1689 he->addr, n->n.prefix, pxlen);
1690 goto done;
1691 }
1692
1693 if (a->dest == RTD_DEVICE)
1694 {
1695 if (if_local_addr(he->addr, a->iface))
1696 {
1697 /* The host address is a local address, this is not valid */
1698 log(L_WARN "Next hop address %I is a local address of iface %s",
1699 he->addr, a->iface->name);
1700 goto done;
1701 }
1702
1703 /* The host is directly reachable, use link as a gateway */
1704 he->gw = he->link;
1705 he->dest = RTD_ROUTER;
1706 }
1707 else
1708 {
1709 /* The host is reachable through some route entry */
1710 he->gw = a->gw;
1711 he->dest = a->dest;
1712 }
1713
1714 he->src = rta_clone(a);
1715 he->igp_metric = rt_get_igp_metric(n->routes);
1716 }
1717
1718 done:
1719 /* Add a prefix range to the trie */
1720 trie_add_prefix(tab->hostcache->trie, he->addr, MAX_PREFIX_LENGTH, pxlen, MAX_PREFIX_LENGTH);
1721
1722 rta_free(old_src);
1723 return old_src != he->src;
1724 }
1725
1726 static void
1727 rt_update_hostcache(rtable *tab)
1728 {
1729 struct hostcache *hc = tab->hostcache;
1730 struct hostentry *he;
1731 node *n, *x;
1732
1733 /* Reset the trie */
1734 lp_flush(hc->lp);
1735 hc->trie = f_new_trie(hc->lp);
1736
1737 WALK_LIST_DELSAFE(n, x, hc->hostentries)
1738 {
1739 he = SKIP_BACK(struct hostentry, ln, n);
1740 if (!he->uc)
1741 {
1742 hc_delete_hostentry(hc, he);
1743 continue;
1744 }
1745
1746 if (rt_update_hostentry(tab, he))
1747 rt_schedule_nhu(he->tab);
1748 }
1749
1750 tab->hcu_scheduled = 0;
1751 }
1752
1753 static struct hostentry *
1754 rt_find_hostentry(rtable *tab, ip_addr a, ip_addr ll, rtable *dep)
1755 {
1756 struct hostentry *he;
1757
1758 if (!tab->hostcache)
1759 rt_init_hostcache(tab);
1760
1761 unsigned int k = hc_hash(a, dep);
1762 struct hostcache *hc = tab->hostcache;
1763 for (he = hc->hash_table[k >> hc->hash_shift]; he != NULL; he = he->next)
1764 if (ipa_equal(he->addr, a) && (he->tab == dep))
1765 return he;
1766
1767 he = hc_new_hostentry(hc, a, ll, dep, k);
1768 rt_update_hostentry(tab, he);
1769 return he;
1770 }
1771
1772 void
1773 rta_set_recursive_next_hop(rtable *dep, rta *a, rtable *tab, ip_addr *gw, ip_addr *ll)
1774 {
1775 rta_apply_hostentry(a, rt_find_hostentry(tab, *gw, *ll, dep));
1776 }
1777
1778 /*
1779 * CLI commands
1780 */
1781
1782 static void
1783 rt_format_via(rte *e, byte *via)
1784 {
1785 rta *a = e->attrs;
1786
1787 switch (a->dest)
1788 {
1789 case RTD_ROUTER: bsprintf(via, "via %I on %s", a->gw, a->iface->name); break;
1790 case RTD_DEVICE: bsprintf(via, "dev %s", a->iface->name); break;
1791 case RTD_BLACKHOLE: bsprintf(via, "blackhole"); break;
1792 case RTD_UNREACHABLE: bsprintf(via, "unreachable"); break;
1793 case RTD_PROHIBIT: bsprintf(via, "prohibited"); break;
1794 case RTD_MULTIPATH: bsprintf(via, "multipath"); break;
1795 default: bsprintf(via, "???");
1796 }
1797 }
1798
1799 static void
1800 rt_show_rte(struct cli *c, byte *ia, rte *e, struct rt_show_data *d, ea_list *tmpa)
1801 {
1802 byte via[STD_ADDRESS_P_LENGTH+32], from[STD_ADDRESS_P_LENGTH+8];
1803 byte tm[TM_DATETIME_BUFFER_SIZE], info[256];
1804 rta *a = e->attrs;
1805 int primary = (e->net->routes == e);
1806 int sync_error = (e->net->n.flags & KRF_SYNC_ERROR);
1807 struct mpnh *nh;
1808
1809 rt_format_via(e, via);
1810 tm_format_datetime(tm, &config->tf_route, e->lastmod);
1811 if (ipa_nonzero(a->from) && !ipa_equal(a->from, a->gw))
1812 bsprintf(from, " from %I", a->from);
1813 else
1814 from[0] = 0;
1815 if (a->proto->proto->get_route_info || d->verbose)
1816 {
1817 /* Need to normalize the extended attributes */
1818 ea_list *t = tmpa;
1819 t = ea_append(t, a->eattrs);
1820 tmpa = alloca(ea_scan(t));
1821 ea_merge(t, tmpa);
1822 ea_sort(tmpa);
1823 }
1824 if (a->proto->proto->get_route_info)
1825 a->proto->proto->get_route_info(e, info, tmpa);
1826 else
1827 bsprintf(info, " (%d)", e->pref);
1828 cli_printf(c, -1007, "%-18s %s [%s %s%s]%s%s", ia, via, a->proto->name,
1829 tm, from, primary ? (sync_error ? " !" : " *") : "", info);
1830 for (nh = a->nexthops; nh; nh = nh->next)
1831 cli_printf(c, -1007, "\tvia %I on %s weight %d", nh->gw, nh->iface->name, nh->weight + 1);
1832 if (d->verbose)
1833 rta_show(c, a, tmpa);
1834 }
1835
1836 static void
1837 rt_show_net(struct cli *c, net *n, struct rt_show_data *d)
1838 {
1839 rte *e, *ee;
1840 byte ia[STD_ADDRESS_P_LENGTH+8];
1841 struct announce_hook *a;
1842 int ok;
1843
1844 bsprintf(ia, "%I/%d", n->n.prefix, n->n.pxlen);
1845 if (n->routes)
1846 d->net_counter++;
1847 for(e=n->routes; e; e=e->next)
1848 {
1849 struct ea_list *tmpa, *old_tmpa;
1850 struct proto *p0 = e->attrs->proto;
1851 struct proto *p1 = d->export_protocol;
1852 struct proto *p2 = d->show_protocol;
1853 d->rt_counter++;
1854 ee = e;
1855 rte_update_lock(); /* We use the update buffer for filtering */
1856 old_tmpa = tmpa = p0->make_tmp_attrs ? p0->make_tmp_attrs(e, rte_update_pool) : NULL;
1857 ok = (d->filter == FILTER_ACCEPT || f_run(d->filter, &e, &tmpa, rte_update_pool, FF_FORCE_TMPATTR) <= F_ACCEPT);
1858 if (p2 && p2 != p0) ok = 0;
1859 if (ok && d->export_mode)
1860 {
1861 int ic;
1862 if ((ic = p1->import_control ? p1->import_control(p1, &e, &tmpa, rte_update_pool) : 0) < 0)
1863 ok = 0;
1864 else if (!ic && d->export_mode > 1)
1865 {
1866 /* FIXME - this shows what should be exported according
1867 to current filters, but not what was really exported.
1868 'configure soft' command may change the export filter
1869 and do not update routes */
1870
1871 if ((a = proto_find_announce_hook(p1, d->table)) && ((a->out_filter == FILTER_REJECT) ||
1872 (a->out_filter && f_run(a->out_filter, &e, &tmpa, rte_update_pool, FF_FORCE_TMPATTR) > F_ACCEPT)))
1873 ok = 0;
1874 }
1875 }
1876 if (ok)
1877 {
1878 d->show_counter++;
1879 if (d->stats < 2)
1880 rt_show_rte(c, ia, e, d, tmpa);
1881 ia[0] = 0;
1882 }
1883 if (e != ee)
1884 {
1885 rte_free(e);
1886 e = ee;
1887 }
1888 rte_update_unlock();
1889 if (d->primary_only)
1890 break;
1891 }
1892 }
1893
1894 static void
1895 rt_show_cont(struct cli *c)
1896 {
1897 struct rt_show_data *d = c->rover;
1898 #ifdef DEBUGGING
1899 unsigned max = 4;
1900 #else
1901 unsigned max = 64;
1902 #endif
1903 struct fib *fib = &d->table->fib;
1904 struct fib_iterator *it = &d->fit;
1905
1906 FIB_ITERATE_START(fib, it, f)
1907 {
1908 net *n = (net *) f;
1909 if (d->running_on_config && d->running_on_config != config)
1910 {
1911 cli_printf(c, 8004, "Stopped due to reconfiguration");
1912 goto done;
1913 }
1914 if (d->export_protocol &&
1915 d->export_protocol->core_state != FS_HAPPY &&
1916 d->export_protocol->core_state != FS_FEEDING)
1917 {
1918 cli_printf(c, 8005, "Protocol is down");
1919 goto done;
1920 }
1921 if (!max--)
1922 {
1923 FIB_ITERATE_PUT(it, f);
1924 return;
1925 }
1926 rt_show_net(c, n, d);
1927 }
1928 FIB_ITERATE_END(f);
1929 if (d->stats)
1930 cli_printf(c, 14, "%d of %d routes for %d networks", d->show_counter, d->rt_counter, d->net_counter);
1931 else
1932 cli_printf(c, 0, "");
1933 done:
1934 c->cont = c->cleanup = NULL;
1935 }
1936
1937 static void
1938 rt_show_cleanup(struct cli *c)
1939 {
1940 struct rt_show_data *d = c->rover;
1941
1942 /* Unlink the iterator */
1943 fit_get(&d->table->fib, &d->fit);
1944 }
1945
1946 void
1947 rt_show(struct rt_show_data *d)
1948 {
1949 net *n;
1950
1951 if (d->pxlen == 256)
1952 {
1953 FIB_ITERATE_INIT(&d->fit, &d->table->fib);
1954 this_cli->cont = rt_show_cont;
1955 this_cli->cleanup = rt_show_cleanup;
1956 this_cli->rover = d;
1957 }
1958 else
1959 {
1960 if (d->show_for)
1961 n = net_route(d->table, d->prefix, d->pxlen);
1962 else
1963 n = net_find(d->table, d->prefix, d->pxlen);
1964 if (n)
1965 {
1966 rt_show_net(this_cli, n, d);
1967 cli_msg(0, "");
1968 }
1969 else
1970 cli_msg(8001, "Network not in table");
1971 }
1972 }
1973
1974 /*
1975 * Documentation for functions declared inline in route.h
1976 */
1977 #if 0
1978
1979 /**
1980 * net_find - find a network entry
1981 * @tab: a routing table
1982 * @addr: address of the network
1983 * @len: length of the network prefix
1984 *
1985 * net_find() looks up the given network in routing table @tab and
1986 * returns a pointer to its &net entry or %NULL if no such network
1987 * exists.
1988 */
1989 static inline net *net_find(rtable *tab, ip_addr addr, unsigned len)
1990 { DUMMY; }
1991
1992 /**
1993 * net_get - obtain a network entry
1994 * @tab: a routing table
1995 * @addr: address of the network
1996 * @len: length of the network prefix
1997 *
1998 * net_get() looks up the given network in routing table @tab and
1999 * returns a pointer to its &net entry. If no such entry exists, it's
2000 * created.
2001 */
2002 static inline net *net_get(rtable *tab, ip_addr addr, unsigned len)
2003 { DUMMY; }
2004
2005 /**
2006 * rte_cow - copy a route for writing
2007 * @r: a route entry to be copied
2008 *
2009 * rte_cow() takes a &rte and prepares it for modification. The exact action
2010 * taken depends on the flags of the &rte -- if it's a temporary entry, it's
2011 * just returned unchanged, else a new temporary entry with the same contents
2012 * is created.
2013 *
2014 * The primary use of this function is inside the filter machinery -- when
2015 * a filter wants to modify &rte contents (to change the preference or to
2016 * attach another set of attributes), it must ensure that the &rte is not
2017 * shared with anyone else (and especially that it isn't stored in any routing
2018 * table).
2019 *
2020 * Result: a pointer to the new writable &rte.
2021 */
2022 static inline rte * rte_cow(rte *r)
2023 { DUMMY; }
2024
2025 #endif