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

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

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