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