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

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
1.1.1.3 ! misho     441:     {
        !           442:       isis_route_info_delete (rinfo_new);
        !           443:       return NULL;
        !           444:     }
        !           445: 
1.1       misho     446:   rinfo_old = route_node->info;
                    447:   if (!rinfo_old)
                    448:     {
                    449:       if (isis->debugs & DEBUG_RTE_EVENTS)
1.1.1.2   misho     450:         zlog_debug ("ISIS-Rte (%s) route created: %s", area->area_tag, buff);
                    451:       route_info = rinfo_new;
                    452:       UNSET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
1.1       misho     453:     }
                    454:   else
                    455:     {
1.1.1.2   misho     456:       if (isis->debugs & DEBUG_RTE_EVENTS)
                    457:         zlog_debug ("ISIS-Rte (%s) route already exists: %s", area->area_tag,
                    458:                    buff);
                    459:       if (isis_route_info_same (rinfo_new, rinfo_old, family))
                    460:         {
                    461:           if (isis->debugs & DEBUG_RTE_EVENTS)
                    462:             zlog_debug ("ISIS-Rte (%s) route unchanged: %s", area->area_tag,
                    463:                         buff);
                    464:           isis_route_info_delete (rinfo_new);
                    465:           route_info = rinfo_old;
                    466:         }
1.1       misho     467:       else
1.1.1.2   misho     468:         {
                    469:           if (isis->debugs & DEBUG_RTE_EVENTS)
                    470:             zlog_debug ("ISIS-Rte (%s) route changed: %s", area->area_tag,
                    471:                         buff);
                    472:           isis_route_info_delete (rinfo_old);
                    473:           route_info = rinfo_new;
                    474:           UNSET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
                    475:         }
1.1       misho     476:     }
                    477: 
                    478:   SET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ACTIVE);
                    479:   route_node->info = route_info;
                    480: 
                    481:   return route_info;
                    482: }
                    483: 
                    484: static void
                    485: isis_route_delete (struct prefix *prefix, struct route_table *table)
                    486: {
                    487:   struct route_node *rode;
                    488:   struct isis_route_info *rinfo;
                    489:   char buff[BUFSIZ];
                    490: 
                    491:   /* for log */
                    492:   prefix2str (prefix, buff, BUFSIZ);
                    493: 
                    494: 
                    495:   rode = route_node_get (table, prefix);
                    496:   rinfo = rode->info;
                    497: 
                    498:   if (rinfo == NULL)
                    499:     {
                    500:       if (isis->debugs & DEBUG_RTE_EVENTS)
                    501:        zlog_debug ("ISIS-Rte: tried to delete non-existant route %s", buff);
                    502:       return;
                    503:     }
                    504: 
1.1.1.2   misho     505:   if (CHECK_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED))
1.1       misho     506:     {
                    507:       UNSET_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ACTIVE);
                    508:       if (isis->debugs & DEBUG_RTE_EVENTS)
                    509:        zlog_debug ("ISIS-Rte: route delete  %s", buff);
                    510:       isis_zebra_route_update (prefix, rinfo);
                    511:     }
                    512:   isis_route_info_delete (rinfo);
                    513:   rode->info = NULL;
                    514: 
                    515:   return;
                    516: }
                    517: 
                    518: /* Validating routes in particular table. */
                    519: static void
                    520: isis_route_validate_table (struct isis_area *area, struct route_table *table)
                    521: {
                    522:   struct route_node *rnode, *drnode;
                    523:   struct isis_route_info *rinfo;
                    524:   u_char buff[BUFSIZ];
                    525: 
                    526:   for (rnode = route_top (table); rnode; rnode = route_next (rnode))
                    527:     {
                    528:       if (rnode->info == NULL)
                    529:        continue;
                    530:       rinfo = rnode->info;
                    531: 
                    532:       if (isis->debugs & DEBUG_RTE_EVENTS)
                    533:        {
                    534:          prefix2str (&rnode->p, (char *) buff, BUFSIZ);
1.1.1.2   misho     535:          zlog_debug ("ISIS-Rte (%s): route validate: %s %s %s %s",
1.1       misho     536:                      area->area_tag,
1.1.1.2   misho     537:                      (CHECK_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED) ?
                    538:                      "synced" : "not-synced"),
                    539:                      (CHECK_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ZEBRA_RESYNC) ?
                    540:                      "resync" : "not-resync"),
1.1       misho     541:                      (CHECK_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ACTIVE) ?
                    542:                      "active" : "inactive"), buff);
                    543:        }
                    544: 
                    545:       isis_zebra_route_update (&rnode->p, rinfo);
                    546:       if (!CHECK_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ACTIVE))
                    547:        {
                    548:          /* Area is either L1 or L2 => we use level route tables directly for
                    549:           * validating => no problems with deleting routes. */
                    550:          if (area->is_type != IS_LEVEL_1_AND_2)
                    551:            {
                    552:              isis_route_delete (&rnode->p, table);
                    553:              continue;
                    554:            }
                    555:          /* If area is L1L2, we work with merge table and therefore must
                    556:           * delete node from level tables as well before deleting route info.
                    557:           * FIXME: Is it performance problem? There has to be the better way.
                    558:           * Like not to deal with it here at all (see the next comment)? */
                    559:          if (rnode->p.family == AF_INET)
                    560:            {
                    561:              drnode = route_node_get (area->route_table[0], &rnode->p);
                    562:              if (drnode->info == rnode->info)
                    563:                drnode->info = NULL;
                    564:              drnode = route_node_get (area->route_table[1], &rnode->p);
                    565:              if (drnode->info == rnode->info)
                    566:                drnode->info = NULL;
                    567:            }
                    568: 
                    569: #ifdef HAVE_IPV6
                    570:          if (rnode->p.family == AF_INET6)
                    571:            {
                    572:              drnode = route_node_get (area->route_table6[0], &rnode->p);
                    573:              if (drnode->info == rnode->info)
                    574:                drnode->info = NULL;
                    575:              drnode = route_node_get (area->route_table6[1], &rnode->p);
                    576:              if (drnode->info == rnode->info)
                    577:                drnode->info = NULL;
                    578:            }
                    579: #endif
                    580:              
                    581:          isis_route_delete (&rnode->p, table);
                    582:        }
                    583:     }
                    584: }
                    585: 
                    586: /* Function to validate route tables for L1L2 areas. In this case we can't use
                    587:  * level route tables directly, we have to merge them at first. L1 routes are
                    588:  * preferred over the L2 ones.
                    589:  *
                    590:  * Merge algorithm is trivial (at least for now). All L1 paths are copied into
                    591:  * merge table at first, then L2 paths are added if L1 path for same prefix
                    592:  * doesn't already exists there.
                    593:  *
                    594:  * FIXME: Is it right place to do it at all? Maybe we should push both levels
                    595:  * to the RIB with different zebra route types and let RIB handle this? */
                    596: static void
                    597: isis_route_validate_merge (struct isis_area *area, int family)
                    598: {
                    599:   struct route_table *table = NULL;
                    600:   struct route_table *merge;
                    601:   struct route_node *rnode, *mrnode;
                    602: 
                    603:   merge = route_table_init ();
                    604: 
                    605:   if (family == AF_INET)
                    606:     table = area->route_table[0];
                    607: #ifdef HAVE_IPV6
                    608:   else if (family == AF_INET6)
                    609:     table = area->route_table6[0];
                    610: #endif
                    611: 
                    612:   for (rnode = route_top (table); rnode; rnode = route_next (rnode))
                    613:     {
                    614:       if (rnode->info == NULL)
                    615:         continue;
                    616:       mrnode = route_node_get (merge, &rnode->p);
                    617:       mrnode->info = rnode->info;
                    618:     }
                    619: 
                    620:   if (family == AF_INET)
                    621:     table = area->route_table[1];
                    622: #ifdef HAVE_IPV6
                    623:   else if (family == AF_INET6)
                    624:     table = area->route_table6[1];
                    625: #endif
                    626: 
                    627:   for (rnode = route_top (table); rnode; rnode = route_next (rnode))
                    628:     {
                    629:       if (rnode->info == NULL)
                    630:         continue;
                    631:       mrnode = route_node_get (merge, &rnode->p);
                    632:       if (mrnode->info != NULL)
                    633:         continue;
                    634:       mrnode->info = rnode->info;
                    635:     }
                    636: 
                    637:   isis_route_validate_table (area, merge);
                    638:   route_table_finish (merge);
                    639: }
                    640: 
                    641: /* Walk through route tables and propagate necessary changes into RIB. In case
                    642:  * of L1L2 area, level tables have to be merged at first. */
1.1.1.2   misho     643: void
                    644: isis_route_validate (struct isis_area *area)
1.1       misho     645: {
1.1.1.2   misho     646:   struct listnode *node;
                    647:   struct isis_circuit *circuit;
1.1       misho     648: 
                    649:   if (area->is_type == IS_LEVEL_1)
1.1.1.2   misho     650:     isis_route_validate_table (area, area->route_table[0]);
                    651:   else if (area->is_type == IS_LEVEL_2)
                    652:     isis_route_validate_table (area, area->route_table[1]);
                    653:   else
                    654:     isis_route_validate_merge (area, AF_INET);
1.1       misho     655: 
                    656: #ifdef HAVE_IPV6
                    657:   if (area->is_type == IS_LEVEL_1)
1.1.1.2   misho     658:     isis_route_validate_table (area, area->route_table6[0]);
                    659:   else if (area->is_type == IS_LEVEL_2)
                    660:     isis_route_validate_table (area, area->route_table6[1]);
                    661:   else
                    662:     isis_route_validate_merge (area, AF_INET6);
                    663: #endif
                    664: 
                    665:   /* walk all circuits and reset any spf specific flags */
                    666:   for (ALL_LIST_ELEMENTS_RO (area->circuit_list, node, circuit))
                    667:     UNSET_FLAG(circuit->flags, ISIS_CIRCUIT_FLAPPED_AFTER_SPF);
                    668: 
                    669:   return;
                    670: }
                    671: 
                    672: void
                    673: isis_route_invalidate_table (struct isis_area *area, struct route_table *table)
                    674: {
                    675:   struct route_node *rode;
                    676:   struct isis_route_info *rinfo;
                    677:   for (rode = route_top (table); rode; rode = route_next (rode))
1.1       misho     678:     {
1.1.1.2   misho     679:       if (rode->info == NULL)
                    680:         continue;
                    681:       rinfo = rode->info;
1.1       misho     682: 
1.1.1.2   misho     683:       UNSET_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ACTIVE);
                    684:     }
                    685: }
1.1       misho     686: 
1.1.1.2   misho     687: void
                    688: isis_route_invalidate (struct isis_area *area)
                    689: {
                    690:   if (area->is_type & IS_LEVEL_1)
                    691:     isis_route_invalidate_table (area, area->route_table[0]);
                    692:   if (area->is_type & IS_LEVEL_2)
                    693:     isis_route_invalidate_table (area, area->route_table[1]);
1.1       misho     694: }

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