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