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