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