Annotation of embedaddon/quagga/isisd/isis_route.c, revision 1.1.1.2

1.1       misho       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"
1.1.1.2 ! misho      39: #include "isis_flags.h"
1.1       misho      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);
1.1.1.2 ! misho     247:           nh->router_address = adj->router_address;
1.1       misho     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);
1.1.1.2 ! misho     271:           nh6->router_address6 = adj->router_address6;
1.1       misho     272:          listnode_add (nexthops6, nh6);
                    273:        }
                    274:     }
                    275: }
                    276: #endif /* HAVE_IPV6 */
                    277: 
                    278: static struct isis_route_info *
1.1.1.2 ! misho     279: isis_route_info_new (struct prefix *prefix, uint32_t cost, uint32_t depth,
        !           280:                      struct list *adjacencies)
1.1       misho     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: 
1.1.1.2 ! misho     293:   if (prefix->family == AF_INET)
1.1       misho     294:     {
                    295:       rinfo->nexthops = list_new ();
                    296:       for (ALL_LIST_ELEMENTS_RO (adjacencies, node, adj))
1.1.1.2 ! misho     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:         }
1.1       misho     306:     }
                    307: #ifdef HAVE_IPV6
1.1.1.2 ! misho     308:   if (prefix->family == AF_INET6)
1.1       misho     309:     {
                    310:       rinfo->nexthops6 = list_new ();
                    311:       for (ALL_LIST_ELEMENTS_RO (adjacencies, node, adj))
1.1.1.2 ! misho     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:         }
1.1       misho     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 */
1.1.1.2 ! misho     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: 
1.1       misho     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))
1.1.1.2 ! misho     385:         if (nexthoplookup (old->nexthops, &nexthop->ip, nexthop->ifindex)
1.1       misho     386:               == 0)
                    387:           return 0;
                    388: 
                    389:       for (ALL_LIST_ELEMENTS_RO (old->nexthops, node, nexthop))
1.1.1.2 ! misho     390:         if (nexthoplookup (new->nexthops, &nexthop->ip, nexthop->ifindex)
1.1       misho     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: 
1.1.1.2 ! misho     426:   rinfo_new = isis_route_info_new (prefix, cost, depth, adjacencies);
1.1       misho     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)
1.1.1.2 ! misho     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);
1.1       misho     449:     }
                    450:   else
                    451:     {
1.1.1.2 ! misho     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:         }
1.1       misho     463:       else
1.1.1.2 ! misho     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:         }
1.1       misho     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: 
1.1.1.2 ! misho     501:   if (CHECK_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED))
1.1       misho     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);
1.1.1.2 ! misho     531:          zlog_debug ("ISIS-Rte (%s): route validate: %s %s %s %s",
1.1       misho     532:                      area->area_tag,
1.1.1.2 ! misho     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"),
1.1       misho     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. */
1.1.1.2 ! misho     639: void
        !           640: isis_route_validate (struct isis_area *area)
1.1       misho     641: {
1.1.1.2 ! misho     642:   struct listnode *node;
        !           643:   struct isis_circuit *circuit;
1.1       misho     644: 
                    645:   if (area->is_type == IS_LEVEL_1)
1.1.1.2 ! misho     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);
1.1       misho     651: 
                    652: #ifdef HAVE_IPV6
                    653:   if (area->is_type == IS_LEVEL_1)
1.1.1.2 ! misho     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))
1.1       misho     674:     {
1.1.1.2 ! misho     675:       if (rode->info == NULL)
        !           676:         continue;
        !           677:       rinfo = rode->info;
1.1       misho     678: 
1.1.1.2 ! misho     679:       UNSET_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ACTIVE);
        !           680:     }
        !           681: }
1.1       misho     682: 
1.1.1.2 ! misho     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]);
1.1       misho     690: }

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