File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / quagga / isisd / isis_route.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Oct 9 09:22:28 2012 UTC (11 years, 8 months ago) by misho
Branches: quagga, MAIN
CVS tags: v0_99_21, HEAD
quagga

    1: /*
    2:  * IS-IS Rout(e)ing protocol               - isis_route.c
    3:  * Copyright (C) 2001,2002   Sampo Saaristo
    4:  *                           Tampere University of Technology      
    5:  *                           Institute of Communications Engineering
    6:  *
    7:  *                                         based on ../ospf6d/ospf6_route.[ch]
    8:  *                                         by Yasuhiro Ohara
    9:  *
   10:  * This program is free software; you can redistribute it and/or modify it 
   11:  * under the terms of the GNU General Public Licenseas published by the Free 
   12:  * Software Foundation; either version 2 of the License, or (at your option) 
   13:  * any later version.
   14:  *
   15:  * This program is distributed in the hope that it will be useful,but WITHOUT 
   16:  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
   17:  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for 
   18:  * more details.
   19: 
   20:  * You should have received a copy of the GNU General Public License along 
   21:  * with this program; if not, write to the Free Software Foundation, Inc., 
   22:  * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
   23:  */
   24: 
   25: #include <zebra.h>
   26: 
   27: #include "thread.h"
   28: #include "linklist.h"
   29: #include "vty.h"
   30: #include "log.h"
   31: #include "memory.h"
   32: #include "prefix.h"
   33: #include "hash.h"
   34: #include "if.h"
   35: #include "table.h"
   36: 
   37: #include "isis_constants.h"
   38: #include "isis_common.h"
   39: #include "isis_flags.h"
   40: #include "dict.h"
   41: #include "isisd.h"
   42: #include "isis_misc.h"
   43: #include "isis_adjacency.h"
   44: #include "isis_circuit.h"
   45: #include "isis_tlv.h"
   46: #include "isis_pdu.h"
   47: #include "isis_lsp.h"
   48: #include "isis_spf.h"
   49: #include "isis_route.h"
   50: #include "isis_zebra.h"
   51: 
   52: static struct isis_nexthop *
   53: isis_nexthop_create (struct in_addr *ip, unsigned int ifindex)
   54: {
   55:   struct listnode *node;
   56:   struct isis_nexthop *nexthop;
   57: 
   58:   for (ALL_LIST_ELEMENTS_RO (isis->nexthops, node, nexthop))
   59:     {
   60:       if (nexthop->ifindex != ifindex)
   61: 	continue;
   62:       if (ip && memcmp (&nexthop->ip, ip, sizeof (struct in_addr)) != 0)
   63: 	continue;
   64: 
   65:       nexthop->lock++;
   66:       return nexthop;
   67:     }
   68: 
   69:   nexthop = XCALLOC (MTYPE_ISIS_NEXTHOP, sizeof (struct isis_nexthop));
   70:   if (!nexthop)
   71:     {
   72:       zlog_err ("ISIS-Rte: isis_nexthop_create: out of memory!");
   73:     }
   74: 
   75:   nexthop->ifindex = ifindex;
   76:   memcpy (&nexthop->ip, ip, sizeof (struct in_addr));
   77:   listnode_add (isis->nexthops, nexthop);
   78:   nexthop->lock++;
   79: 
   80:   return nexthop;
   81: }
   82: 
   83: static void
   84: isis_nexthop_delete (struct isis_nexthop *nexthop)
   85: {
   86:   nexthop->lock--;
   87:   if (nexthop->lock == 0)
   88:     {
   89:       listnode_delete (isis->nexthops, nexthop);
   90:       XFREE (MTYPE_ISIS_NEXTHOP, nexthop);
   91:     }
   92: 
   93:   return;
   94: }
   95: 
   96: static int
   97: nexthoplookup (struct list *nexthops, struct in_addr *ip,
   98: 	       unsigned int ifindex)
   99: {
  100:   struct listnode *node;
  101:   struct isis_nexthop *nh;
  102: 
  103:   for (ALL_LIST_ELEMENTS_RO (nexthops, node, nh))
  104:     {
  105:       if (!(memcmp (ip, &nh->ip, sizeof (struct in_addr))) &&
  106: 	  ifindex == nh->ifindex)
  107: 	return 1;
  108:     }
  109: 
  110:   return 0;
  111: }
  112: 
  113: #ifdef EXTREME_DEBUG
  114: static void
  115: nexthop_print (struct isis_nexthop *nh)
  116: {
  117:   u_char buf[BUFSIZ];
  118: 
  119:   inet_ntop (AF_INET, &nh->ip, (char *) buf, BUFSIZ);
  120: 
  121:   zlog_debug ("      %s %u", buf, nh->ifindex);
  122: }
  123: 
  124: static void
  125: nexthops_print (struct list *nhs)
  126: {
  127:   struct listnode *node;
  128:   struct isis_nexthop *nh;
  129: 
  130:   for (ALL_LIST_ELEMENTS_RO (nhs, node, nh))
  131:     nexthop_print (nh);
  132: }
  133: #endif /* EXTREME_DEBUG */
  134: 
  135: #ifdef HAVE_IPV6
  136: static struct isis_nexthop6 *
  137: isis_nexthop6_new (struct in6_addr *ip6, unsigned int ifindex)
  138: {
  139:   struct isis_nexthop6 *nexthop6;
  140: 
  141:   nexthop6 = XCALLOC (MTYPE_ISIS_NEXTHOP6, sizeof (struct isis_nexthop6));
  142:   if (!nexthop6)
  143:     {
  144:       zlog_err ("ISIS-Rte: isis_nexthop_create6: out of memory!");
  145:     }
  146: 
  147:   nexthop6->ifindex = ifindex;
  148:   memcpy (&nexthop6->ip6, ip6, sizeof (struct in6_addr));
  149:   nexthop6->lock++;
  150: 
  151:   return nexthop6;
  152: }
  153: 
  154: static struct isis_nexthop6 *
  155: isis_nexthop6_create (struct in6_addr *ip6, unsigned int ifindex)
  156: {
  157:   struct listnode *node;
  158:   struct isis_nexthop6 *nexthop6;
  159: 
  160:   for (ALL_LIST_ELEMENTS_RO (isis->nexthops6, node, nexthop6))
  161:     {
  162:       if (nexthop6->ifindex != ifindex)
  163: 	continue;
  164:       if (ip6 && memcmp (&nexthop6->ip6, ip6, sizeof (struct in6_addr)) != 0)
  165: 	continue;
  166: 
  167:       nexthop6->lock++;
  168:       return nexthop6;
  169:     }
  170: 
  171:   nexthop6 = isis_nexthop6_new (ip6, ifindex);
  172: 
  173:   return nexthop6;
  174: }
  175: 
  176: static void
  177: isis_nexthop6_delete (struct isis_nexthop6 *nexthop6)
  178: {
  179: 
  180:   nexthop6->lock--;
  181:   if (nexthop6->lock == 0)
  182:     {
  183:       listnode_delete (isis->nexthops6, nexthop6);
  184:       XFREE (MTYPE_ISIS_NEXTHOP6, nexthop6);
  185:     }
  186: 
  187:   return;
  188: }
  189: 
  190: static int
  191: nexthop6lookup (struct list *nexthops6, struct in6_addr *ip6,
  192: 		unsigned int ifindex)
  193: {
  194:   struct listnode *node;
  195:   struct isis_nexthop6 *nh6;
  196: 
  197:   for (ALL_LIST_ELEMENTS_RO (nexthops6, node, nh6))
  198:     {
  199:       if (!(memcmp (ip6, &nh6->ip6, sizeof (struct in6_addr))) &&
  200: 	  ifindex == nh6->ifindex)
  201: 	return 1;
  202:     }
  203: 
  204:   return 0;
  205: }
  206: 
  207: #ifdef EXTREME_DEBUG
  208: static void
  209: nexthop6_print (struct isis_nexthop6 *nh6)
  210: {
  211:   u_char buf[BUFSIZ];
  212: 
  213:   inet_ntop (AF_INET6, &nh6->ip6, (char *) buf, BUFSIZ);
  214: 
  215:   zlog_debug ("      %s %u", buf, nh6->ifindex);
  216: }
  217: 
  218: static void
  219: nexthops6_print (struct list *nhs6)
  220: {
  221:   struct listnode *node;
  222:   struct isis_nexthop6 *nh6;
  223: 
  224:   for (ALL_LIST_ELEMENTS_RO (nhs6, node, nh6))
  225:     nexthop6_print (nh6);
  226: }
  227: #endif /* EXTREME_DEBUG */
  228: #endif /* HAVE_IPV6 */
  229: 
  230: static void
  231: adjinfo2nexthop (struct list *nexthops, struct isis_adjacency *adj)
  232: {
  233:   struct isis_nexthop *nh;
  234:   struct listnode *node;
  235:   struct in_addr *ipv4_addr;
  236: 
  237:   if (adj->ipv4_addrs == NULL)
  238:     return;
  239: 
  240:   for (ALL_LIST_ELEMENTS_RO (adj->ipv4_addrs, node, ipv4_addr))
  241:     {
  242:       if (!nexthoplookup (nexthops, ipv4_addr,
  243: 			  adj->circuit->interface->ifindex))
  244: 	{
  245: 	  nh = isis_nexthop_create (ipv4_addr,
  246: 				    adj->circuit->interface->ifindex);
  247:           nh->router_address = adj->router_address;
  248: 	  listnode_add (nexthops, nh);
  249: 	}
  250:     }
  251: }
  252: 
  253: #ifdef HAVE_IPV6
  254: static void
  255: adjinfo2nexthop6 (struct list *nexthops6, struct isis_adjacency *adj)
  256: {
  257:   struct listnode *node;
  258:   struct in6_addr *ipv6_addr;
  259:   struct isis_nexthop6 *nh6;
  260: 
  261:   if (!adj->ipv6_addrs)
  262:     return;
  263: 
  264:   for (ALL_LIST_ELEMENTS_RO (adj->ipv6_addrs, node, ipv6_addr))
  265:     {
  266:       if (!nexthop6lookup (nexthops6, ipv6_addr,
  267: 			   adj->circuit->interface->ifindex))
  268: 	{
  269: 	  nh6 = isis_nexthop6_create (ipv6_addr,
  270: 				      adj->circuit->interface->ifindex);
  271:           nh6->router_address6 = adj->router_address6;
  272: 	  listnode_add (nexthops6, nh6);
  273: 	}
  274:     }
  275: }
  276: #endif /* HAVE_IPV6 */
  277: 
  278: static struct isis_route_info *
  279: isis_route_info_new (struct prefix *prefix, uint32_t cost, uint32_t depth,
  280:                      struct list *adjacencies)
  281: {
  282:   struct isis_route_info *rinfo;
  283:   struct isis_adjacency *adj;
  284:   struct listnode *node;
  285: 
  286:   rinfo = XCALLOC (MTYPE_ISIS_ROUTE_INFO, sizeof (struct isis_route_info));
  287:   if (!rinfo)
  288:     {
  289:       zlog_err ("ISIS-Rte: isis_route_info_new: out of memory!");
  290:       return NULL;
  291:     }
  292: 
  293:   if (prefix->family == AF_INET)
  294:     {
  295:       rinfo->nexthops = list_new ();
  296:       for (ALL_LIST_ELEMENTS_RO (adjacencies, node, adj))
  297:         {
  298:           /* check for force resync this route */
  299:           if (CHECK_FLAG (adj->circuit->flags, ISIS_CIRCUIT_FLAPPED_AFTER_SPF))
  300:             SET_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ZEBRA_RESYNC);
  301:           /* update neighbor router address */
  302:           if (depth == 2 && prefix->prefixlen == 32)
  303:             adj->router_address = prefix->u.prefix4;
  304:           adjinfo2nexthop (rinfo->nexthops, adj);
  305:         }
  306:     }
  307: #ifdef HAVE_IPV6
  308:   if (prefix->family == AF_INET6)
  309:     {
  310:       rinfo->nexthops6 = list_new ();
  311:       for (ALL_LIST_ELEMENTS_RO (adjacencies, node, adj))
  312:         {
  313:           /* check for force resync this route */
  314:           if (CHECK_FLAG (adj->circuit->flags, ISIS_CIRCUIT_FLAPPED_AFTER_SPF))
  315:             SET_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ZEBRA_RESYNC);
  316:           /* update neighbor router address */
  317:           if (depth == 2 && prefix->prefixlen == 128)
  318:             adj->router_address6 = prefix->u.prefix6;
  319:           adjinfo2nexthop6 (rinfo->nexthops6, adj);
  320:         }
  321:     }
  322: 
  323: #endif /* HAVE_IPV6 */
  324: 
  325:   rinfo->cost = cost;
  326:   rinfo->depth = depth;
  327: 
  328:   return rinfo;
  329: }
  330: 
  331: static void
  332: isis_route_info_delete (struct isis_route_info *route_info)
  333: {
  334:   if (route_info->nexthops)
  335:     {
  336:       route_info->nexthops->del = (void (*)(void *)) isis_nexthop_delete;
  337:       list_delete (route_info->nexthops);
  338:     }
  339: 
  340: #ifdef HAVE_IPV6
  341:   if (route_info->nexthops6)
  342:     {
  343:       route_info->nexthops6->del = (void (*)(void *)) isis_nexthop6_delete;
  344:       list_delete (route_info->nexthops6);
  345:     }
  346: #endif /* HAVE_IPV6 */
  347: 
  348:   XFREE (MTYPE_ISIS_ROUTE_INFO, route_info);
  349: }
  350: 
  351: static int
  352: isis_route_info_same_attrib (struct isis_route_info *new,
  353: 			     struct isis_route_info *old)
  354: {
  355:   if (new->cost != old->cost)
  356:     return 0;
  357:   if (new->depth != old->depth)
  358:     return 0;
  359: 
  360:   return 1;
  361: }
  362: 
  363: static int
  364: isis_route_info_same (struct isis_route_info *new,
  365: 		      struct isis_route_info *old, u_char family)
  366: {
  367:   struct listnode *node;
  368:   struct isis_nexthop *nexthop;
  369: #ifdef HAVE_IPV6
  370:   struct isis_nexthop6 *nexthop6;
  371: #endif /* HAVE_IPV6 */
  372: 
  373:   if (!CHECK_FLAG (old->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED))
  374:     return 0;
  375: 
  376:   if (CHECK_FLAG (new->flag, ISIS_ROUTE_FLAG_ZEBRA_RESYNC))
  377:     return 0;
  378: 
  379:   if (!isis_route_info_same_attrib (new, old))
  380:     return 0;
  381: 
  382:   if (family == AF_INET)
  383:     {
  384:       for (ALL_LIST_ELEMENTS_RO (new->nexthops, node, nexthop))
  385:         if (nexthoplookup (old->nexthops, &nexthop->ip, nexthop->ifindex)
  386:               == 0)
  387:           return 0;
  388: 
  389:       for (ALL_LIST_ELEMENTS_RO (old->nexthops, node, nexthop))
  390:         if (nexthoplookup (new->nexthops, &nexthop->ip, nexthop->ifindex)
  391:              == 0)
  392:           return 0;
  393:     }
  394: #ifdef HAVE_IPV6
  395:   else if (family == AF_INET6)
  396:     {
  397:       for (ALL_LIST_ELEMENTS_RO (new->nexthops6, node, nexthop6))
  398:         if (nexthop6lookup (old->nexthops6, &nexthop6->ip6,
  399:                             nexthop6->ifindex) == 0)
  400:           return 0;
  401: 
  402:       for (ALL_LIST_ELEMENTS_RO (old->nexthops6, node, nexthop6))
  403:         if (nexthop6lookup (new->nexthops6, &nexthop6->ip6,
  404:                             nexthop6->ifindex) == 0)
  405:           return 0;
  406:     }
  407: #endif /* HAVE_IPV6 */
  408: 
  409:   return 1;
  410: }
  411: 
  412: struct isis_route_info *
  413: isis_route_create (struct prefix *prefix, u_int32_t cost, u_int32_t depth,
  414: 		   struct list *adjacencies, struct isis_area *area,
  415: 		   int level)
  416: {
  417:   struct route_node *route_node;
  418:   struct isis_route_info *rinfo_new, *rinfo_old, *route_info = NULL;
  419:   u_char buff[BUFSIZ];
  420:   u_char family;
  421: 
  422:   family = prefix->family;
  423:   /* for debugs */
  424:   prefix2str (prefix, (char *) buff, BUFSIZ);
  425: 
  426:   rinfo_new = isis_route_info_new (prefix, cost, depth, adjacencies);
  427:   if (!rinfo_new)
  428:     {
  429:       zlog_err ("ISIS-Rte (%s): isis_route_create: out of memory!",
  430: 		area->area_tag);
  431:       return NULL;
  432:     }
  433: 
  434:   if (family == AF_INET)
  435:     route_node = route_node_get (area->route_table[level - 1], prefix);
  436: #ifdef HAVE_IPV6
  437:   else if (family == AF_INET6)
  438:     route_node = route_node_get (area->route_table6[level - 1], prefix);
  439: #endif /* HAVE_IPV6 */
  440:   else
  441:     return NULL;
  442:   rinfo_old = route_node->info;
  443:   if (!rinfo_old)
  444:     {
  445:       if (isis->debugs & DEBUG_RTE_EVENTS)
  446:         zlog_debug ("ISIS-Rte (%s) route created: %s", area->area_tag, buff);
  447:       route_info = rinfo_new;
  448:       UNSET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
  449:     }
  450:   else
  451:     {
  452:       if (isis->debugs & DEBUG_RTE_EVENTS)
  453:         zlog_debug ("ISIS-Rte (%s) route already exists: %s", area->area_tag,
  454:                    buff);
  455:       if (isis_route_info_same (rinfo_new, rinfo_old, family))
  456:         {
  457:           if (isis->debugs & DEBUG_RTE_EVENTS)
  458:             zlog_debug ("ISIS-Rte (%s) route unchanged: %s", area->area_tag,
  459:                         buff);
  460:           isis_route_info_delete (rinfo_new);
  461:           route_info = rinfo_old;
  462:         }
  463:       else
  464:         {
  465:           if (isis->debugs & DEBUG_RTE_EVENTS)
  466:             zlog_debug ("ISIS-Rte (%s) route changed: %s", area->area_tag,
  467:                         buff);
  468:           isis_route_info_delete (rinfo_old);
  469:           route_info = rinfo_new;
  470:           UNSET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
  471:         }
  472:     }
  473: 
  474:   SET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ACTIVE);
  475:   route_node->info = route_info;
  476: 
  477:   return route_info;
  478: }
  479: 
  480: static void
  481: isis_route_delete (struct prefix *prefix, struct route_table *table)
  482: {
  483:   struct route_node *rode;
  484:   struct isis_route_info *rinfo;
  485:   char buff[BUFSIZ];
  486: 
  487:   /* for log */
  488:   prefix2str (prefix, buff, BUFSIZ);
  489: 
  490: 
  491:   rode = route_node_get (table, prefix);
  492:   rinfo = rode->info;
  493: 
  494:   if (rinfo == NULL)
  495:     {
  496:       if (isis->debugs & DEBUG_RTE_EVENTS)
  497: 	zlog_debug ("ISIS-Rte: tried to delete non-existant route %s", buff);
  498:       return;
  499:     }
  500: 
  501:   if (CHECK_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED))
  502:     {
  503:       UNSET_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ACTIVE);
  504:       if (isis->debugs & DEBUG_RTE_EVENTS)
  505: 	zlog_debug ("ISIS-Rte: route delete  %s", buff);
  506:       isis_zebra_route_update (prefix, rinfo);
  507:     }
  508:   isis_route_info_delete (rinfo);
  509:   rode->info = NULL;
  510: 
  511:   return;
  512: }
  513: 
  514: /* Validating routes in particular table. */
  515: static void
  516: isis_route_validate_table (struct isis_area *area, struct route_table *table)
  517: {
  518:   struct route_node *rnode, *drnode;
  519:   struct isis_route_info *rinfo;
  520:   u_char buff[BUFSIZ];
  521: 
  522:   for (rnode = route_top (table); rnode; rnode = route_next (rnode))
  523:     {
  524:       if (rnode->info == NULL)
  525: 	continue;
  526:       rinfo = rnode->info;
  527: 
  528:       if (isis->debugs & DEBUG_RTE_EVENTS)
  529: 	{
  530: 	  prefix2str (&rnode->p, (char *) buff, BUFSIZ);
  531: 	  zlog_debug ("ISIS-Rte (%s): route validate: %s %s %s %s",
  532: 		      area->area_tag,
  533: 		      (CHECK_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED) ?
  534: 		      "synced" : "not-synced"),
  535: 		      (CHECK_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ZEBRA_RESYNC) ?
  536: 		      "resync" : "not-resync"),
  537: 		      (CHECK_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ACTIVE) ?
  538: 		      "active" : "inactive"), buff);
  539: 	}
  540: 
  541:       isis_zebra_route_update (&rnode->p, rinfo);
  542:       if (!CHECK_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ACTIVE))
  543: 	{
  544: 	  /* Area is either L1 or L2 => we use level route tables directly for
  545: 	   * validating => no problems with deleting routes. */
  546: 	  if (area->is_type != IS_LEVEL_1_AND_2)
  547: 	    {
  548: 	      isis_route_delete (&rnode->p, table);
  549: 	      continue;
  550: 	    }
  551: 	  /* If area is L1L2, we work with merge table and therefore must
  552: 	   * delete node from level tables as well before deleting route info.
  553: 	   * FIXME: Is it performance problem? There has to be the better way.
  554: 	   * Like not to deal with it here at all (see the next comment)? */
  555: 	  if (rnode->p.family == AF_INET)
  556: 	    {
  557: 	      drnode = route_node_get (area->route_table[0], &rnode->p);
  558: 	      if (drnode->info == rnode->info)
  559: 		drnode->info = NULL;
  560: 	      drnode = route_node_get (area->route_table[1], &rnode->p);
  561: 	      if (drnode->info == rnode->info)
  562: 		drnode->info = NULL;
  563: 	    }
  564: 
  565: #ifdef HAVE_IPV6
  566: 	  if (rnode->p.family == AF_INET6)
  567: 	    {
  568: 	      drnode = route_node_get (area->route_table6[0], &rnode->p);
  569: 	      if (drnode->info == rnode->info)
  570: 		drnode->info = NULL;
  571: 	      drnode = route_node_get (area->route_table6[1], &rnode->p);
  572: 	      if (drnode->info == rnode->info)
  573: 		drnode->info = NULL;
  574: 	    }
  575: #endif
  576: 	      
  577: 	  isis_route_delete (&rnode->p, table);
  578: 	}
  579:     }
  580: }
  581: 
  582: /* Function to validate route tables for L1L2 areas. In this case we can't use
  583:  * level route tables directly, we have to merge them at first. L1 routes are
  584:  * preferred over the L2 ones.
  585:  *
  586:  * Merge algorithm is trivial (at least for now). All L1 paths are copied into
  587:  * merge table at first, then L2 paths are added if L1 path for same prefix
  588:  * doesn't already exists there.
  589:  *
  590:  * FIXME: Is it right place to do it at all? Maybe we should push both levels
  591:  * to the RIB with different zebra route types and let RIB handle this? */
  592: static void
  593: isis_route_validate_merge (struct isis_area *area, int family)
  594: {
  595:   struct route_table *table = NULL;
  596:   struct route_table *merge;
  597:   struct route_node *rnode, *mrnode;
  598: 
  599:   merge = route_table_init ();
  600: 
  601:   if (family == AF_INET)
  602:     table = area->route_table[0];
  603: #ifdef HAVE_IPV6
  604:   else if (family == AF_INET6)
  605:     table = area->route_table6[0];
  606: #endif
  607: 
  608:   for (rnode = route_top (table); rnode; rnode = route_next (rnode))
  609:     {
  610:       if (rnode->info == NULL)
  611:         continue;
  612:       mrnode = route_node_get (merge, &rnode->p);
  613:       mrnode->info = rnode->info;
  614:     }
  615: 
  616:   if (family == AF_INET)
  617:     table = area->route_table[1];
  618: #ifdef HAVE_IPV6
  619:   else if (family == AF_INET6)
  620:     table = area->route_table6[1];
  621: #endif
  622: 
  623:   for (rnode = route_top (table); rnode; rnode = route_next (rnode))
  624:     {
  625:       if (rnode->info == NULL)
  626:         continue;
  627:       mrnode = route_node_get (merge, &rnode->p);
  628:       if (mrnode->info != NULL)
  629:         continue;
  630:       mrnode->info = rnode->info;
  631:     }
  632: 
  633:   isis_route_validate_table (area, merge);
  634:   route_table_finish (merge);
  635: }
  636: 
  637: /* Walk through route tables and propagate necessary changes into RIB. In case
  638:  * of L1L2 area, level tables have to be merged at first. */
  639: void
  640: isis_route_validate (struct isis_area *area)
  641: {
  642:   struct listnode *node;
  643:   struct isis_circuit *circuit;
  644: 
  645:   if (area->is_type == IS_LEVEL_1)
  646:     isis_route_validate_table (area, area->route_table[0]);
  647:   else if (area->is_type == IS_LEVEL_2)
  648:     isis_route_validate_table (area, area->route_table[1]);
  649:   else
  650:     isis_route_validate_merge (area, AF_INET);
  651: 
  652: #ifdef HAVE_IPV6
  653:   if (area->is_type == IS_LEVEL_1)
  654:     isis_route_validate_table (area, area->route_table6[0]);
  655:   else if (area->is_type == IS_LEVEL_2)
  656:     isis_route_validate_table (area, area->route_table6[1]);
  657:   else
  658:     isis_route_validate_merge (area, AF_INET6);
  659: #endif
  660: 
  661:   /* walk all circuits and reset any spf specific flags */
  662:   for (ALL_LIST_ELEMENTS_RO (area->circuit_list, node, circuit))
  663:     UNSET_FLAG(circuit->flags, ISIS_CIRCUIT_FLAPPED_AFTER_SPF);
  664: 
  665:   return;
  666: }
  667: 
  668: void
  669: isis_route_invalidate_table (struct isis_area *area, struct route_table *table)
  670: {
  671:   struct route_node *rode;
  672:   struct isis_route_info *rinfo;
  673:   for (rode = route_top (table); rode; rode = route_next (rode))
  674:     {
  675:       if (rode->info == NULL)
  676:         continue;
  677:       rinfo = rode->info;
  678: 
  679:       UNSET_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ACTIVE);
  680:     }
  681: }
  682: 
  683: void
  684: isis_route_invalidate (struct isis_area *area)
  685: {
  686:   if (area->is_type & IS_LEVEL_1)
  687:     isis_route_invalidate_table (area, area->route_table[0]);
  688:   if (area->is_type & IS_LEVEL_2)
  689:     isis_route_invalidate_table (area, area->route_table[1]);
  690: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>