Annotation of embedaddon/quagga/ospf6d/ospf6_abr.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * Area Border Router function.
        !             3:  * Copyright (C) 2004 Yasuhiro Ohara
        !             4:  *
        !             5:  * This file is part of GNU Zebra.
        !             6:  *
        !             7:  * GNU Zebra is free software; you can redistribute it and/or modify it
        !             8:  * under the terms of the GNU General Public License as published by the
        !             9:  * Free Software Foundation; either version 2, or (at your option) any
        !            10:  * later version.
        !            11:  *
        !            12:  * GNU Zebra is distributed in the hope that it will be useful, but
        !            13:  * WITHOUT ANY WARRANTY; without even the implied warranty of
        !            14:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
        !            15:  * General Public License for more details.
        !            16:  *
        !            17:  * You should have received a copy of the GNU General Public License
        !            18:  * along with GNU Zebra; see the file COPYING.  If not, write to the 
        !            19:  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 
        !            20:  * Boston, MA 02111-1307, USA.  
        !            21:  */
        !            22: 
        !            23: #include <zebra.h>
        !            24: 
        !            25: #include "log.h"
        !            26: #include "prefix.h"
        !            27: #include "table.h"
        !            28: #include "vty.h"
        !            29: #include "linklist.h"
        !            30: #include "command.h"
        !            31: #include "thread.h"
        !            32: #include "plist.h"
        !            33: #include "filter.h"
        !            34: 
        !            35: #include "ospf6_proto.h"
        !            36: #include "ospf6_route.h"
        !            37: #include "ospf6_lsa.h"
        !            38: #include "ospf6_route.h"
        !            39: #include "ospf6_lsdb.h"
        !            40: #include "ospf6_message.h"
        !            41: 
        !            42: #include "ospf6_top.h"
        !            43: #include "ospf6_area.h"
        !            44: #include "ospf6_interface.h"
        !            45: #include "ospf6_neighbor.h"
        !            46: 
        !            47: #include "ospf6_flood.h"
        !            48: #include "ospf6_intra.h"
        !            49: #include "ospf6_abr.h"
        !            50: #include "ospf6d.h"
        !            51: 
        !            52: unsigned char conf_debug_ospf6_abr;
        !            53: 
        !            54: int
        !            55: ospf6_is_router_abr (struct ospf6 *o)
        !            56: {
        !            57:   struct listnode *node;
        !            58:   struct ospf6_area *oa;
        !            59:   int area_count = 0;
        !            60: 
        !            61:   for (ALL_LIST_ELEMENTS_RO (o->area_list, node, oa))
        !            62:     if (IS_AREA_ENABLED (oa))
        !            63:       area_count++;
        !            64: 
        !            65:   if (area_count > 1)
        !            66:     return 1;
        !            67:   return 0;
        !            68: }
        !            69: 
        !            70: void
        !            71: ospf6_abr_enable_area (struct ospf6_area *area)
        !            72: {
        !            73:   struct ospf6_area *oa;
        !            74:   struct ospf6_route *ro;
        !            75:   struct listnode *node, *nnode;
        !            76: 
        !            77:   for (ALL_LIST_ELEMENTS (area->ospf6->area_list, node, nnode, oa))
        !            78:     {
        !            79:       /* update B bit for each area */
        !            80:       OSPF6_ROUTER_LSA_SCHEDULE (oa);
        !            81: 
        !            82:       /* install other area's configured address range */
        !            83:       if (oa != area)
        !            84:         {
        !            85:           for (ro = ospf6_route_head (oa->range_table); ro;
        !            86:                ro = ospf6_route_next (ro))
        !            87:             {
        !            88:               if (CHECK_FLAG (ro->flag, OSPF6_ROUTE_ACTIVE_SUMMARY))
        !            89:                 ospf6_abr_originate_summary_to_area (ro, area);
        !            90:             }
        !            91:         }
        !            92:     }
        !            93: 
        !            94:   /* install calculated routes to border routers */
        !            95:   for (ro = ospf6_route_head (area->ospf6->brouter_table); ro;
        !            96:        ro = ospf6_route_next (ro))
        !            97:     ospf6_abr_originate_summary_to_area (ro, area);
        !            98: 
        !            99:   /* install calculated routes to network (may be rejected by ranges) */
        !           100:   for (ro = ospf6_route_head (area->ospf6->route_table); ro;
        !           101:        ro = ospf6_route_next (ro))
        !           102:     ospf6_abr_originate_summary_to_area (ro, area);
        !           103: }
        !           104: 
        !           105: void
        !           106: ospf6_abr_disable_area (struct ospf6_area *area)
        !           107: {
        !           108:   struct ospf6_area *oa;
        !           109:   struct ospf6_route *ro;
        !           110:   struct ospf6_lsa *old;
        !           111:   struct listnode *node, *nnode;
        !           112: 
        !           113:   /* Withdraw all summary prefixes previously originated */
        !           114:   for (ro = ospf6_route_head (area->summary_prefix); ro;
        !           115:        ro = ospf6_route_next (ro))
        !           116:     {
        !           117:       old = ospf6_lsdb_lookup (ro->path.origin.type, ro->path.origin.id,
        !           118:                                area->ospf6->router_id, area->lsdb);
        !           119:       if (old)
        !           120:         ospf6_lsa_purge (old);
        !           121:       ospf6_route_remove (ro, area->summary_prefix);
        !           122:     }
        !           123: 
        !           124:   /* Withdraw all summary router-routes previously originated */
        !           125:   for (ro = ospf6_route_head (area->summary_router); ro;
        !           126:        ro = ospf6_route_next (ro))
        !           127:     {
        !           128:       old = ospf6_lsdb_lookup (ro->path.origin.type, ro->path.origin.id,
        !           129:                                area->ospf6->router_id, area->lsdb);
        !           130:       if (old)
        !           131:         ospf6_lsa_purge (old);
        !           132:       ospf6_route_remove (ro, area->summary_router);
        !           133:     }
        !           134: 
        !           135:   /* Schedule Router-LSA for each area (ABR status may change) */
        !           136:   for (ALL_LIST_ELEMENTS (area->ospf6->area_list, node, nnode, oa))
        !           137:     /* update B bit for each area */
        !           138:     OSPF6_ROUTER_LSA_SCHEDULE (oa);
        !           139: }
        !           140: 
        !           141: /* RFC 2328 12.4.3. Summary-LSAs */
        !           142: void
        !           143: ospf6_abr_originate_summary_to_area (struct ospf6_route *route,
        !           144:                                      struct ospf6_area *area)
        !           145: {
        !           146:   struct ospf6_lsa *lsa, *old = NULL;
        !           147:   struct ospf6_interface *oi;
        !           148:   struct ospf6_route *summary, *range = NULL;
        !           149:   struct ospf6_area *route_area;
        !           150:   char buffer[OSPF6_MAX_LSASIZE];
        !           151:   struct ospf6_lsa_header *lsa_header;
        !           152:   caddr_t p;
        !           153:   struct ospf6_inter_prefix_lsa *prefix_lsa;
        !           154:   struct ospf6_inter_router_lsa *router_lsa;
        !           155:   struct ospf6_route_table *summary_table = NULL;
        !           156:   u_int16_t type;
        !           157:   char buf[64];
        !           158:   int is_debug = 0;
        !           159: 
        !           160:   if (route->type == OSPF6_DEST_TYPE_ROUTER)
        !           161:     {
        !           162:       if (IS_OSPF6_DEBUG_ABR || IS_OSPF6_DEBUG_ORIGINATE (INTER_ROUTER))
        !           163:         {
        !           164:           is_debug++;
        !           165:           inet_ntop (AF_INET, &(ADV_ROUTER_IN_PREFIX (&route->prefix)),
        !           166:                      buf, sizeof (buf));
        !           167:           zlog_debug ("Originating summary in area %s for ASBR %s",
        !           168:                      area->name, buf);
        !           169:         }
        !           170:       summary_table = area->summary_router;
        !           171:     }
        !           172:   else
        !           173:     {
        !           174:       if (IS_OSPF6_DEBUG_ABR || IS_OSPF6_DEBUG_ORIGINATE (INTER_PREFIX))
        !           175:         {
        !           176:           is_debug++;
        !           177:           prefix2str (&route->prefix, buf, sizeof (buf));
        !           178:           zlog_debug ("Originating summary in area %s for %s",
        !           179:                      area->name, buf);
        !           180:         }
        !           181:       summary_table = area->summary_prefix;
        !           182:     }
        !           183: 
        !           184:   summary = ospf6_route_lookup (&route->prefix, summary_table);
        !           185:   if (summary)
        !           186:     old = ospf6_lsdb_lookup (summary->path.origin.type,
        !           187:                              summary->path.origin.id,
        !           188:                              area->ospf6->router_id, area->lsdb);
        !           189: 
        !           190:   /* if this route has just removed, remove corresponding LSA */
        !           191:   if (CHECK_FLAG (route->flag, OSPF6_ROUTE_REMOVE))
        !           192:     {
        !           193:       if (is_debug)
        !           194:         zlog_debug ("The route has just removed, purge previous LSA");
        !           195:       if (summary)
        !           196:         ospf6_route_remove (summary, summary_table);
        !           197:       if (old)
        !           198:         ospf6_lsa_purge (old);
        !           199:       return;
        !           200:     }
        !           201: 
        !           202:   /* Only destination type network, range or ASBR are considered */
        !           203:   if (route->type != OSPF6_DEST_TYPE_NETWORK &&
        !           204:       route->type != OSPF6_DEST_TYPE_RANGE &&
        !           205:       (route->type != OSPF6_DEST_TYPE_ROUTER ||
        !           206:        ! CHECK_FLAG (route->path.router_bits, OSPF6_ROUTER_BIT_E)))
        !           207:     {
        !           208:       if (is_debug)
        !           209:         zlog_debug ("Route type is none of network, range nor ASBR, withdraw");
        !           210:       if (summary)
        !           211:         ospf6_route_remove (summary, summary_table);
        !           212:       if (old)
        !           213:         ospf6_lsa_purge (old);
        !           214:       return;
        !           215:     }
        !           216: 
        !           217:   /* AS External routes are never considered */
        !           218:   if (route->path.type == OSPF6_PATH_TYPE_EXTERNAL1 ||
        !           219:       route->path.type == OSPF6_PATH_TYPE_EXTERNAL2)
        !           220:     {
        !           221:       if (is_debug)
        !           222:         zlog_debug ("Path type is external, withdraw");
        !           223:       if (summary)
        !           224:         ospf6_route_remove (summary, summary_table);
        !           225:       if (old)
        !           226:         ospf6_lsa_purge (old);
        !           227:       return;
        !           228:     }
        !           229: 
        !           230:   /* do not generate if the path's area is the same as target area */
        !           231:   if (route->path.area_id == area->area_id)
        !           232:     {
        !           233:       if (is_debug)
        !           234:         zlog_debug ("The route is in the area itself, ignore");
        !           235:       if (summary)
        !           236:         ospf6_route_remove (summary, summary_table);
        !           237:       if (old)
        !           238:         ospf6_lsa_purge (old);
        !           239:       return;
        !           240:     }
        !           241: 
        !           242:   /* do not generate if the nexthops belongs to the target area */
        !           243:   oi = ospf6_interface_lookup_by_ifindex (route->nexthop[0].ifindex);
        !           244:   if (oi && oi->area && oi->area == area)
        !           245:     {
        !           246:       if (is_debug)
        !           247:         zlog_debug ("The route's nexthop is in the same area, ignore");
        !           248:       if (summary)
        !           249:         ospf6_route_remove (summary, summary_table);
        !           250:       if (old)
        !           251:         ospf6_lsa_purge (old);
        !           252:       return;
        !           253:     }
        !           254: 
        !           255:   /* do not generate if the route cost is greater or equal to LSInfinity */
        !           256:   if (route->path.cost >= LS_INFINITY)
        !           257:     {
        !           258:       if (is_debug)
        !           259:         zlog_debug ("The cost exceeds LSInfinity, withdraw");
        !           260:       if (summary)
        !           261:         ospf6_route_remove (summary, summary_table);
        !           262:       if (old)
        !           263:         ospf6_lsa_purge (old);
        !           264:       return;
        !           265:     }
        !           266: 
        !           267:   /* if this is a route to ASBR */
        !           268:   if (route->type == OSPF6_DEST_TYPE_ROUTER)
        !           269:     {
        !           270:       /* Only the prefered best path is considered */
        !           271:       if (! CHECK_FLAG (route->flag, OSPF6_ROUTE_BEST))
        !           272:         {
        !           273:           if (is_debug)
        !           274:             zlog_debug ("This is the secondary path to the ASBR, ignore");
        !           275:           if (summary)
        !           276:             ospf6_route_remove (summary, summary_table);
        !           277:           if (old)
        !           278:             ospf6_lsa_purge (old);
        !           279:           return;
        !           280:         }
        !           281: 
        !           282:       /* Do not generate if the area is stub */
        !           283:       /* XXX */
        !           284:     }
        !           285: 
        !           286:   /* if this is an intra-area route, this may be suppressed by aggregation */
        !           287:   if (route->type == OSPF6_DEST_TYPE_NETWORK &&
        !           288:       route->path.type == OSPF6_PATH_TYPE_INTRA)
        !           289:     {
        !           290:       /* search for configured address range for the route's area */
        !           291:       route_area = ospf6_area_lookup (route->path.area_id, area->ospf6);
        !           292:       assert (route_area);
        !           293:       range = ospf6_route_lookup_bestmatch (&route->prefix,
        !           294:                                             route_area->range_table);
        !           295: 
        !           296:       /* ranges are ignored when originate backbone routes to transit area.
        !           297:          Otherwise, if ranges are configured, the route is suppressed. */
        !           298:       if (range && ! CHECK_FLAG (range->flag, OSPF6_ROUTE_REMOVE) &&
        !           299:           (route->path.area_id != BACKBONE_AREA_ID ||
        !           300:            ! IS_AREA_TRANSIT (area)))
        !           301:         {
        !           302:           if (is_debug)
        !           303:             {
        !           304:               prefix2str (&range->prefix, buf, sizeof (buf));
        !           305:               zlog_debug ("Suppressed by range %s of area %s",
        !           306:                          buf, route_area->name);
        !           307:             }
        !           308: 
        !           309:           if (summary)
        !           310:             ospf6_route_remove (summary, summary_table);
        !           311:           if (old)
        !           312:             ospf6_lsa_purge (old);
        !           313:           return;
        !           314:         }
        !           315:     }
        !           316: 
        !           317:   /* If this is a configured address range */
        !           318:   if (route->type == OSPF6_DEST_TYPE_RANGE)
        !           319:     {
        !           320:       /* If DoNotAdvertise is set */
        !           321:       if (CHECK_FLAG (route->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE))
        !           322:         {
        !           323:           if (is_debug)
        !           324:             zlog_debug ("This is the range with DoNotAdvertise set. ignore");
        !           325:           if (summary)
        !           326:             ospf6_route_remove (summary, summary_table);
        !           327:           if (old)
        !           328:             ospf6_lsa_purge (old);
        !           329:           return;
        !           330:         }
        !           331: 
        !           332:       /* Whether the route have active longer prefix */
        !           333:       if (! CHECK_FLAG (route->flag, OSPF6_ROUTE_ACTIVE_SUMMARY))
        !           334:         {
        !           335:           if (is_debug)
        !           336:             zlog_debug ("The range is not active. withdraw");
        !           337:           if (summary)
        !           338:             ospf6_route_remove (summary, summary_table);
        !           339:           if (old)
        !           340:             ospf6_lsa_purge (old);
        !           341:           return;
        !           342:         }
        !           343:     }
        !           344: 
        !           345:   /* Check export list */
        !           346:   if (EXPORT_NAME (area))
        !           347:     {
        !           348:       if (EXPORT_LIST (area) == NULL)
        !           349:         EXPORT_LIST (area) =
        !           350:           access_list_lookup (AFI_IP6, EXPORT_NAME (area));
        !           351: 
        !           352:       if (EXPORT_LIST (area))
        !           353:         if (access_list_apply (EXPORT_LIST (area),
        !           354:                                &route->prefix) == FILTER_DENY)
        !           355:           {
        !           356:             if (is_debug)
        !           357:               {
        !           358:                 inet_ntop (AF_INET, &(ADV_ROUTER_IN_PREFIX (&route->prefix)),
        !           359:                            buf, sizeof(buf));
        !           360:                 zlog_debug ("prefix %s was denied by export list", buf);
        !           361:               }
        !           362:             return;
        !           363:           }
        !           364:     }
        !           365: 
        !           366:   /* Check filter-list */
        !           367:   if (PREFIX_NAME_OUT (area))
        !           368:     {
        !           369:       if (PREFIX_LIST_OUT (area) == NULL)
        !           370:         PREFIX_LIST_OUT (area) =
        !           371:           prefix_list_lookup(AFI_IP6, PREFIX_NAME_OUT (area));
        !           372: 
        !           373:       if (PREFIX_LIST_OUT (area))
        !           374:          if (prefix_list_apply (PREFIX_LIST_OUT (area), 
        !           375:                                 &route->prefix) != PREFIX_PERMIT) 
        !           376:            {
        !           377:              if (is_debug)
        !           378:                {
        !           379:                  inet_ntop (AF_INET, &(ADV_ROUTER_IN_PREFIX (&route->prefix)),
        !           380:                             buf, sizeof (buf));
        !           381:                  zlog_debug ("prefix %s was denied by filter-list out", buf);
        !           382:                }
        !           383:              return;
        !           384:            }
        !           385:     }
        !           386: 
        !           387:   /* the route is going to be originated. store it in area's summary_table */
        !           388:   if (summary == NULL)
        !           389:     {
        !           390:       summary = ospf6_route_copy (route);
        !           391:       if (route->type == OSPF6_DEST_TYPE_NETWORK ||
        !           392:           route->type == OSPF6_DEST_TYPE_RANGE)
        !           393:         summary->path.origin.type = htons (OSPF6_LSTYPE_INTER_PREFIX);
        !           394:       else
        !           395:         summary->path.origin.type = htons (OSPF6_LSTYPE_INTER_ROUTER);
        !           396:       summary->path.origin.adv_router = area->ospf6->router_id;
        !           397:       summary->path.origin.id =
        !           398:         ospf6_new_ls_id (summary->path.origin.type,
        !           399:                          summary->path.origin.adv_router, area->lsdb);
        !           400:       summary = ospf6_route_add (summary, summary_table);
        !           401:     }
        !           402:   else
        !           403:     {
        !           404:       summary->type = route->type;
        !           405:       quagga_gettime (QUAGGA_CLK_MONOTONIC, &summary->changed);
        !           406:     }
        !           407: 
        !           408:   summary->path.router_bits = route->path.router_bits;
        !           409:   summary->path.options[0] = route->path.options[0];
        !           410:   summary->path.options[1] = route->path.options[1];
        !           411:   summary->path.options[2] = route->path.options[2];
        !           412:   summary->path.prefix_options = route->path.prefix_options;
        !           413:   summary->path.area_id = area->area_id;
        !           414:   summary->path.type = OSPF6_PATH_TYPE_INTER;
        !           415:   summary->path.cost = route->path.cost;
        !           416:   summary->nexthop[0] = route->nexthop[0];
        !           417: 
        !           418:   /* prepare buffer */
        !           419:   memset (buffer, 0, sizeof (buffer));
        !           420:   lsa_header = (struct ospf6_lsa_header *) buffer;
        !           421: 
        !           422:   if (route->type == OSPF6_DEST_TYPE_ROUTER)
        !           423:     {
        !           424:       router_lsa = (struct ospf6_inter_router_lsa *)
        !           425:         ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header));
        !           426:       p = (caddr_t) router_lsa + sizeof (struct ospf6_inter_router_lsa);
        !           427: 
        !           428:       /* Fill Inter-Area-Router-LSA */
        !           429:       router_lsa->options[0] = route->path.options[0];
        !           430:       router_lsa->options[1] = route->path.options[1];
        !           431:       router_lsa->options[2] = route->path.options[2];
        !           432:       OSPF6_ABR_SUMMARY_METRIC_SET (router_lsa, route->path.cost);
        !           433:       router_lsa->router_id = ADV_ROUTER_IN_PREFIX (&route->prefix);
        !           434:       type = htons (OSPF6_LSTYPE_INTER_ROUTER);
        !           435:     }
        !           436:   else
        !           437:     {
        !           438:       prefix_lsa = (struct ospf6_inter_prefix_lsa *)
        !           439:         ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header));
        !           440:       p = (caddr_t) prefix_lsa + sizeof (struct ospf6_inter_prefix_lsa);
        !           441: 
        !           442:       /* Fill Inter-Area-Prefix-LSA */
        !           443:       OSPF6_ABR_SUMMARY_METRIC_SET (prefix_lsa, route->path.cost);
        !           444:       prefix_lsa->prefix.prefix_length = route->prefix.prefixlen;
        !           445:       prefix_lsa->prefix.prefix_options = route->path.prefix_options;
        !           446: 
        !           447:       /* set Prefix */
        !           448:       memcpy (p, &route->prefix.u.prefix6,
        !           449:               OSPF6_PREFIX_SPACE (route->prefix.prefixlen));
        !           450:       ospf6_prefix_apply_mask (&prefix_lsa->prefix);
        !           451:       p += OSPF6_PREFIX_SPACE (route->prefix.prefixlen);
        !           452:       type = htons (OSPF6_LSTYPE_INTER_PREFIX);
        !           453:     }
        !           454: 
        !           455:   /* Fill LSA Header */
        !           456:   lsa_header->age = 0;
        !           457:   lsa_header->type = type;
        !           458:   lsa_header->id = summary->path.origin.id;
        !           459:   lsa_header->adv_router = area->ospf6->router_id;
        !           460:   lsa_header->seqnum =
        !           461:     ospf6_new_ls_seqnum (lsa_header->type, lsa_header->id,
        !           462:                          lsa_header->adv_router, area->lsdb);
        !           463:   lsa_header->length = htons ((caddr_t) p - (caddr_t) lsa_header);
        !           464: 
        !           465:   /* LSA checksum */
        !           466:   ospf6_lsa_checksum (lsa_header);
        !           467: 
        !           468:   /* create LSA */
        !           469:   lsa = ospf6_lsa_create (lsa_header);
        !           470: 
        !           471:   /* Originate */
        !           472:   ospf6_lsa_originate_area (lsa, area);
        !           473: }
        !           474: 
        !           475: static void
        !           476: ospf6_abr_range_update (struct ospf6_route *range)
        !           477: {
        !           478:   u_int32_t cost = 0;
        !           479:   struct ospf6_route *ro;
        !           480: 
        !           481:   assert (range->type == OSPF6_DEST_TYPE_RANGE);
        !           482: 
        !           483:   /* update range's cost and active flag */
        !           484:   for (ro = ospf6_route_match_head (&range->prefix, ospf6->route_table);
        !           485:        ro; ro = ospf6_route_match_next (&range->prefix, ro))
        !           486:     {
        !           487:       if (ro->path.area_id == range->path.area_id &&
        !           488:           ! CHECK_FLAG (ro->flag, OSPF6_ROUTE_REMOVE))
        !           489:         cost = MAX (cost, ro->path.cost);
        !           490:     }
        !           491: 
        !           492:   if (range->path.cost != cost)
        !           493:     {
        !           494:       range->path.cost = cost;
        !           495: 
        !           496:       if (range->path.cost)
        !           497:         SET_FLAG (range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY);
        !           498:       else
        !           499:         UNSET_FLAG (range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY);
        !           500: 
        !           501:       ospf6_abr_originate_summary (range);
        !           502:     }
        !           503: }
        !           504: 
        !           505: void
        !           506: ospf6_abr_originate_summary (struct ospf6_route *route)
        !           507: {
        !           508:   struct listnode *node, *nnode;
        !           509:   struct ospf6_area *oa;
        !           510:   struct ospf6_route *range = NULL;
        !           511: 
        !           512:   if (route->type == OSPF6_DEST_TYPE_NETWORK)
        !           513:     {
        !           514:       oa = ospf6_area_lookup (route->path.area_id, ospf6);
        !           515:       range = ospf6_route_lookup_bestmatch (&route->prefix, oa->range_table);
        !           516:       if (range)
        !           517:         ospf6_abr_range_update (range);
        !           518:     }
        !           519: 
        !           520:   for (ALL_LIST_ELEMENTS (ospf6->area_list, node, nnode, oa))
        !           521:     ospf6_abr_originate_summary_to_area (route, oa);
        !           522: }
        !           523: 
        !           524: /* RFC 2328 16.2. Calculating the inter-area routes */
        !           525: void
        !           526: ospf6_abr_examin_summary (struct ospf6_lsa *lsa, struct ospf6_area *oa)
        !           527: {
        !           528:   struct prefix prefix, abr_prefix;
        !           529:   struct ospf6_route_table *table = NULL;
        !           530:   struct ospf6_route *range, *route, *old = NULL;
        !           531:   struct ospf6_route *abr_entry;
        !           532:   u_char type = 0;
        !           533:   char options[3] = {0, 0, 0};
        !           534:   u_int8_t prefix_options = 0;
        !           535:   u_int32_t cost = 0;
        !           536:   u_char router_bits = 0;
        !           537:   int i;
        !           538:   char buf[64];
        !           539:   int is_debug = 0;
        !           540: 
        !           541:   memset (&prefix, 0, sizeof (prefix));
        !           542: 
        !           543:   if (lsa->header->type == htons (OSPF6_LSTYPE_INTER_PREFIX))
        !           544:     {
        !           545:       struct ospf6_inter_prefix_lsa *prefix_lsa;
        !           546: 
        !           547:       if (IS_OSPF6_DEBUG_EXAMIN (INTER_PREFIX))
        !           548:         {
        !           549:           is_debug++;
        !           550:           zlog_debug ("Examin %s in area %s", lsa->name, oa->name);
        !           551:         }
        !           552: 
        !           553:       prefix_lsa = (struct ospf6_inter_prefix_lsa *)
        !           554:         OSPF6_LSA_HEADER_END (lsa->header);
        !           555:       prefix.family = AF_INET6;
        !           556:       prefix.prefixlen = prefix_lsa->prefix.prefix_length;
        !           557:       ospf6_prefix_in6_addr (&prefix.u.prefix6, &prefix_lsa->prefix);
        !           558:       if (is_debug)
        !           559:         prefix2str (&prefix, buf, sizeof (buf));
        !           560:       table = oa->ospf6->route_table;
        !           561:       type = OSPF6_DEST_TYPE_NETWORK;
        !           562:       prefix_options = prefix_lsa->prefix.prefix_options;
        !           563:       cost = OSPF6_ABR_SUMMARY_METRIC (prefix_lsa);
        !           564:     }
        !           565:   else if (lsa->header->type == htons (OSPF6_LSTYPE_INTER_ROUTER))
        !           566:     {
        !           567:       struct ospf6_inter_router_lsa *router_lsa;
        !           568: 
        !           569:       if (IS_OSPF6_DEBUG_EXAMIN (INTER_ROUTER))
        !           570:         {
        !           571:           is_debug++;
        !           572:           zlog_debug ("Examin %s in area %s", lsa->name, oa->name);
        !           573:         }
        !           574: 
        !           575:       router_lsa = (struct ospf6_inter_router_lsa *)
        !           576:         OSPF6_LSA_HEADER_END (lsa->header);
        !           577:       ospf6_linkstate_prefix (router_lsa->router_id, htonl (0), &prefix);
        !           578:       if (is_debug)
        !           579:         inet_ntop (AF_INET, &router_lsa->router_id, buf, sizeof (buf));
        !           580:       table = oa->ospf6->brouter_table;
        !           581:       type = OSPF6_DEST_TYPE_ROUTER;
        !           582:       options[0] = router_lsa->options[0];
        !           583:       options[1] = router_lsa->options[1];
        !           584:       options[2] = router_lsa->options[2];
        !           585:       cost = OSPF6_ABR_SUMMARY_METRIC (router_lsa);
        !           586:       SET_FLAG (router_bits, OSPF6_ROUTER_BIT_E);
        !           587:     }
        !           588:   else
        !           589:     assert (0);
        !           590: 
        !           591:   /* Find existing route */
        !           592:   route = ospf6_route_lookup (&prefix, table);
        !           593:   if (route)
        !           594:     ospf6_route_lock (route);
        !           595:   while (route && ospf6_route_is_prefix (&prefix, route))
        !           596:     {
        !           597:       if (route->path.area_id == oa->area_id &&
        !           598:           route->path.origin.type == lsa->header->type &&
        !           599:           route->path.origin.id == lsa->header->id &&
        !           600:           route->path.origin.adv_router == lsa->header->adv_router &&
        !           601:           ! CHECK_FLAG (route->flag, OSPF6_ROUTE_WAS_REMOVED))
        !           602:         old = route;
        !           603:       route = ospf6_route_next (route);
        !           604:     }
        !           605: 
        !           606:   /* (1) if cost == LSInfinity or if the LSA is MaxAge */
        !           607:   if (cost == LS_INFINITY)
        !           608:     {
        !           609:       if (is_debug)
        !           610:         zlog_debug ("cost is LS_INFINITY, ignore");
        !           611:       if (old)
        !           612:         ospf6_route_remove (old, table);
        !           613:       return;
        !           614:     }
        !           615:   if (OSPF6_LSA_IS_MAXAGE (lsa))
        !           616:     {
        !           617:       if (is_debug)
        !           618:         zlog_debug ("LSA is MaxAge, ignore");
        !           619:       if (old)
        !           620:         ospf6_route_remove (old, table);
        !           621:       return;
        !           622:     }
        !           623: 
        !           624:   /* (2) if the LSA is self-originated, ignore */
        !           625:   if (lsa->header->adv_router == oa->ospf6->router_id)
        !           626:     {
        !           627:       if (is_debug)
        !           628:         zlog_debug ("LSA is self-originated, ignore");
        !           629:       if (old)
        !           630:         ospf6_route_remove (old, table);
        !           631:       return;
        !           632:     }
        !           633: 
        !           634:   /* (3) if the prefix is equal to an active configured address range */
        !           635:   if (lsa->header->type == htons (OSPF6_LSTYPE_INTER_PREFIX))
        !           636:     {
        !           637:       range = ospf6_route_lookup (&prefix, oa->range_table);
        !           638:       if (range)
        !           639:         {
        !           640:           if (is_debug)
        !           641:             zlog_debug ("Prefix is equal to address range, ignore");
        !           642:           if (old)
        !           643:             ospf6_route_remove (old, table);
        !           644:           return;
        !           645:         }
        !           646:     }
        !           647: 
        !           648:   /* (4) if the routing table entry for the ABR does not exist */
        !           649:   ospf6_linkstate_prefix (lsa->header->adv_router, htonl (0), &abr_prefix);
        !           650:   abr_entry = ospf6_route_lookup (&abr_prefix, oa->ospf6->brouter_table);
        !           651:   if (abr_entry == NULL || abr_entry->path.area_id != oa->area_id ||
        !           652:       CHECK_FLAG (abr_entry->flag, OSPF6_ROUTE_REMOVE) ||
        !           653:       ! CHECK_FLAG (abr_entry->path.router_bits, OSPF6_ROUTER_BIT_B))
        !           654:     {
        !           655:       if (is_debug)
        !           656:         zlog_debug ("ABR router entry does not exist, ignore");
        !           657:       if (old)
        !           658:         ospf6_route_remove (old, table);
        !           659:       return;
        !           660:     }
        !           661: 
        !           662:   /* Check import list */
        !           663:   if (IMPORT_NAME (oa))
        !           664:     {
        !           665:       if (IMPORT_LIST (oa) == NULL)
        !           666:         IMPORT_LIST (oa) = access_list_lookup (AFI_IP6, IMPORT_NAME (oa));
        !           667: 
        !           668:       if (IMPORT_LIST (oa))
        !           669:         if (access_list_apply (IMPORT_LIST (oa), &prefix) == FILTER_DENY)
        !           670:           {
        !           671:             if (is_debug)
        !           672:               zlog_debug ("Prefix was denied by import-list");
        !           673:             if (old)
        !           674:               ospf6_route_remove (old, table);
        !           675:             return;
        !           676:           }
        !           677:     }
        !           678: 
        !           679:   /* Check input prefix-list */
        !           680:   if (PREFIX_NAME_IN (oa))
        !           681:     {
        !           682:       if (PREFIX_LIST_IN (oa) == NULL)
        !           683:         PREFIX_LIST_IN (oa) = prefix_list_lookup (AFI_IP6, PREFIX_NAME_IN (oa));
        !           684: 
        !           685:       if (PREFIX_LIST_IN (oa))
        !           686:         if (prefix_list_apply (PREFIX_LIST_IN (oa), &prefix) != PREFIX_PERMIT)
        !           687:           {
        !           688:             if (is_debug)
        !           689:               zlog_debug ("Prefix was denied by prefix-list");
        !           690:             if (old)
        !           691:               ospf6_route_remove (old, table);
        !           692:             return;
        !           693:           }
        !           694:     }
        !           695: 
        !           696:   /* (5),(6),(7) the path preference is handled by the sorting
        !           697:      in the routing table. Always install the path by substituting
        !           698:      old route (if any). */
        !           699:   if (old)
        !           700:     route = ospf6_route_copy (old);
        !           701:   else
        !           702:     route = ospf6_route_create ();
        !           703: 
        !           704:   route->type = type;
        !           705:   route->prefix = prefix;
        !           706:   route->path.origin.type = lsa->header->type;
        !           707:   route->path.origin.id = lsa->header->id;
        !           708:   route->path.origin.adv_router = lsa->header->adv_router;
        !           709:   route->path.router_bits = router_bits;
        !           710:   route->path.options[0] = options[0];
        !           711:   route->path.options[1] = options[1];
        !           712:   route->path.options[2] = options[2];
        !           713:   route->path.prefix_options = prefix_options;
        !           714:   route->path.area_id = oa->area_id;
        !           715:   route->path.type = OSPF6_PATH_TYPE_INTER;
        !           716:   route->path.cost = abr_entry->path.cost + cost;
        !           717:   for (i = 0; i < OSPF6_MULTI_PATH_LIMIT; i++)
        !           718:     route->nexthop[i] = abr_entry->nexthop[i];
        !           719: 
        !           720:   if (is_debug)
        !           721:     zlog_debug ("Install route: %s", buf);
        !           722:   ospf6_route_add (route, table);
        !           723: }
        !           724: 
        !           725: void
        !           726: ospf6_abr_examin_brouter (u_int32_t router_id)
        !           727: {
        !           728:   struct ospf6_lsa *lsa;
        !           729:   struct ospf6_area *oa;
        !           730:   struct listnode *node, *nnode;
        !           731:   u_int16_t type;
        !           732: 
        !           733:   for (ALL_LIST_ELEMENTS (ospf6->area_list, node, nnode, oa))
        !           734:     {
        !           735:       type = htons (OSPF6_LSTYPE_INTER_ROUTER);
        !           736:       for (lsa = ospf6_lsdb_type_router_head (type, router_id, oa->lsdb); lsa;
        !           737:            lsa = ospf6_lsdb_type_router_next (type, router_id, lsa))
        !           738:         ospf6_abr_examin_summary (lsa, oa);
        !           739: 
        !           740:       type = htons (OSPF6_LSTYPE_INTER_PREFIX);
        !           741:       for (lsa = ospf6_lsdb_type_router_head (type, router_id, oa->lsdb); lsa;
        !           742:            lsa = ospf6_lsdb_type_router_next (type, router_id, lsa))
        !           743:         ospf6_abr_examin_summary (lsa, oa);
        !           744:     }
        !           745: }
        !           746: 
        !           747: void
        !           748: ospf6_abr_reimport (struct ospf6_area *oa)
        !           749: {
        !           750:   struct ospf6_lsa *lsa;
        !           751:   u_int16_t type;
        !           752: 
        !           753:   type = htons (OSPF6_LSTYPE_INTER_ROUTER);
        !           754:   for (lsa = ospf6_lsdb_type_head (type, oa->lsdb); lsa;
        !           755:        lsa = ospf6_lsdb_type_next (type, lsa))
        !           756:     ospf6_abr_examin_summary (lsa, oa);
        !           757: 
        !           758:   type = htons (OSPF6_LSTYPE_INTER_PREFIX);
        !           759:   for (lsa = ospf6_lsdb_type_head (type, oa->lsdb); lsa;
        !           760:        lsa = ospf6_lsdb_type_next (type, lsa))
        !           761:     ospf6_abr_examin_summary (lsa, oa);
        !           762: }
        !           763: 
        !           764: 
        !           765: 
        !           766: /* Display functions */
        !           767: static int
        !           768: ospf6_inter_area_prefix_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
        !           769: {
        !           770:   struct ospf6_inter_prefix_lsa *prefix_lsa;
        !           771:   struct in6_addr in6;
        !           772:   char buf[64];
        !           773: 
        !           774:   prefix_lsa = (struct ospf6_inter_prefix_lsa *)
        !           775:     OSPF6_LSA_HEADER_END (lsa->header);
        !           776: 
        !           777:   vty_out (vty, "     Metric: %lu%s",
        !           778:            (u_long) OSPF6_ABR_SUMMARY_METRIC (prefix_lsa), VNL);
        !           779: 
        !           780:   ospf6_prefix_options_printbuf (prefix_lsa->prefix.prefix_options,
        !           781:                                  buf, sizeof (buf));
        !           782:   vty_out (vty, "     Prefix Options: %s%s", buf, VNL);
        !           783: 
        !           784:   ospf6_prefix_in6_addr (&in6, &prefix_lsa->prefix);
        !           785:   inet_ntop (AF_INET6, &in6, buf, sizeof (buf));
        !           786:   vty_out (vty, "     Prefix: %s/%d%s", buf,
        !           787:            prefix_lsa->prefix.prefix_length, VNL);
        !           788: 
        !           789:   return 0;
        !           790: }
        !           791: 
        !           792: static int
        !           793: ospf6_inter_area_router_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
        !           794: {
        !           795:   struct ospf6_inter_router_lsa *router_lsa;
        !           796:   char buf[64];
        !           797: 
        !           798:   router_lsa = (struct ospf6_inter_router_lsa *)
        !           799:     OSPF6_LSA_HEADER_END (lsa->header);
        !           800: 
        !           801:   ospf6_options_printbuf (router_lsa->options, buf, sizeof (buf));
        !           802:   vty_out (vty, "     Options: %s%s", buf, VNL);
        !           803:   vty_out (vty, "     Metric: %lu%s",
        !           804:            (u_long) OSPF6_ABR_SUMMARY_METRIC (router_lsa), VNL);
        !           805:   inet_ntop (AF_INET, &router_lsa->router_id, buf, sizeof (buf));
        !           806:   vty_out (vty, "     Destination Router ID: %s%s", buf, VNL);
        !           807: 
        !           808:   return 0;
        !           809: }
        !           810: 
        !           811: /* Debug commands */
        !           812: DEFUN (debug_ospf6_abr,
        !           813:        debug_ospf6_abr_cmd,
        !           814:        "debug ospf6 abr",
        !           815:        DEBUG_STR
        !           816:        OSPF6_STR
        !           817:        "Debug OSPFv3 ABR function\n"
        !           818:       )
        !           819: {
        !           820:   OSPF6_DEBUG_ABR_ON ();
        !           821:   return CMD_SUCCESS;
        !           822: }
        !           823: 
        !           824: DEFUN (no_debug_ospf6_abr,
        !           825:        no_debug_ospf6_abr_cmd,
        !           826:        "no debug ospf6 abr",
        !           827:        NO_STR
        !           828:        DEBUG_STR
        !           829:        OSPF6_STR
        !           830:        "Debug OSPFv3 ABR function\n"
        !           831:       )
        !           832: {
        !           833:   OSPF6_DEBUG_ABR_OFF ();
        !           834:   return CMD_SUCCESS;
        !           835: }
        !           836: 
        !           837: int
        !           838: config_write_ospf6_debug_abr (struct vty *vty)
        !           839: {
        !           840:   if (IS_OSPF6_DEBUG_ABR)
        !           841:     vty_out (vty, "debug ospf6 abr%s", VNL);
        !           842:   return 0;
        !           843: }
        !           844: 
        !           845: void
        !           846: install_element_ospf6_debug_abr (void)
        !           847: {
        !           848:   install_element (ENABLE_NODE, &debug_ospf6_abr_cmd);
        !           849:   install_element (ENABLE_NODE, &no_debug_ospf6_abr_cmd);
        !           850:   install_element (CONFIG_NODE, &debug_ospf6_abr_cmd);
        !           851:   install_element (CONFIG_NODE, &no_debug_ospf6_abr_cmd);
        !           852: }
        !           853: 
        !           854: struct ospf6_lsa_handler inter_prefix_handler =
        !           855: {
        !           856:   OSPF6_LSTYPE_INTER_PREFIX,
        !           857:   "Inter-Prefix",
        !           858:   ospf6_inter_area_prefix_lsa_show
        !           859: };
        !           860: 
        !           861: struct ospf6_lsa_handler inter_router_handler =
        !           862: {
        !           863:   OSPF6_LSTYPE_INTER_ROUTER,
        !           864:   "Inter-Router",
        !           865:   ospf6_inter_area_router_lsa_show
        !           866: };
        !           867: 
        !           868: void
        !           869: ospf6_abr_init (void)
        !           870: {
        !           871:   ospf6_install_lsa_handler (&inter_prefix_handler);
        !           872:   ospf6_install_lsa_handler (&inter_router_handler);
        !           873: }
        !           874: 
        !           875: 

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