File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / bird2 / nest / rt-table.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Mon Oct 21 16:03:56 2019 UTC (4 years, 8 months ago) by misho
Branches: bird2, MAIN
CVS tags: v2_0_7p0, HEAD
bird2 ver 2.0.7

    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>