Annotation of embedaddon/quagga/ospfd/ospf_route.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * OSPF routing table.
        !             3:  * Copyright (C) 1999, 2000 Toshiaki Takada
        !             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 Free
        !            19:  * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
        !            20:  * 02111-1307, USA.
        !            21:  */
        !            22: 
        !            23: #include <zebra.h>
        !            24: 
        !            25: #include "prefix.h"
        !            26: #include "table.h"
        !            27: #include "memory.h"
        !            28: #include "linklist.h"
        !            29: #include "log.h"
        !            30: #include "if.h"
        !            31: #include "command.h"
        !            32: #include "sockunion.h"
        !            33: 
        !            34: #include "ospfd/ospfd.h"
        !            35: #include "ospfd/ospf_interface.h"
        !            36: #include "ospfd/ospf_asbr.h"
        !            37: #include "ospfd/ospf_lsa.h"
        !            38: #include "ospfd/ospf_route.h"
        !            39: #include "ospfd/ospf_spf.h"
        !            40: #include "ospfd/ospf_zebra.h"
        !            41: #include "ospfd/ospf_dump.h"
        !            42: 
        !            43: struct ospf_route *
        !            44: ospf_route_new ()
        !            45: {
        !            46:   struct ospf_route *new;
        !            47: 
        !            48:   new = XCALLOC (MTYPE_OSPF_ROUTE, sizeof (struct ospf_route));
        !            49: 
        !            50:   new->ctime = quagga_time (NULL);
        !            51:   new->mtime = new->ctime;
        !            52:   new->paths = list_new ();
        !            53:   new->paths->del = (void (*) (void *))ospf_path_free;
        !            54: 
        !            55:   return new;
        !            56: }
        !            57: 
        !            58: void
        !            59: ospf_route_free (struct ospf_route *or)
        !            60: {
        !            61:   if (or->paths)
        !            62:       list_delete (or->paths);
        !            63: 
        !            64:   XFREE (MTYPE_OSPF_ROUTE, or);
        !            65: }
        !            66: 
        !            67: struct ospf_path *
        !            68: ospf_path_new ()
        !            69: {
        !            70:   struct ospf_path *new;
        !            71: 
        !            72:   new = XCALLOC (MTYPE_OSPF_PATH, sizeof (struct ospf_path));
        !            73: 
        !            74:   return new;
        !            75: }
        !            76: 
        !            77: static struct ospf_path *
        !            78: ospf_path_dup (struct ospf_path *path)
        !            79: {
        !            80:   struct ospf_path *new;
        !            81: 
        !            82:   new = ospf_path_new ();
        !            83:   memcpy (new, path, sizeof (struct ospf_path));
        !            84: 
        !            85:   return new;
        !            86: }
        !            87: 
        !            88: void
        !            89: ospf_path_free (struct ospf_path *op)
        !            90: {
        !            91:   XFREE (MTYPE_OSPF_PATH, op);
        !            92: }
        !            93: 
        !            94: void
        !            95: ospf_route_delete (struct route_table *rt)
        !            96: {
        !            97:   struct route_node *rn;
        !            98:   struct ospf_route *or;
        !            99: 
        !           100:   for (rn = route_top (rt); rn; rn = route_next (rn))
        !           101:     if ((or = rn->info) != NULL)
        !           102:       {
        !           103:        if (or->type == OSPF_DESTINATION_NETWORK)
        !           104:          ospf_zebra_delete ((struct prefix_ipv4 *) &rn->p,
        !           105:                                       or);
        !           106:        else if (or->type == OSPF_DESTINATION_DISCARD)
        !           107:          ospf_zebra_delete_discard ((struct prefix_ipv4 *) &rn->p);
        !           108:       }
        !           109: }
        !           110: 
        !           111: void
        !           112: ospf_route_table_free (struct route_table *rt)
        !           113: {
        !           114:   struct route_node *rn;
        !           115:   struct ospf_route *or;
        !           116: 
        !           117:   for (rn = route_top (rt); rn; rn = route_next (rn))
        !           118:     if ((or = rn->info) != NULL)
        !           119:       {
        !           120:        ospf_route_free (or);
        !           121: 
        !           122:        rn->info = NULL;
        !           123:        route_unlock_node (rn);
        !           124:       }
        !           125: 
        !           126:    route_table_finish (rt);
        !           127: }
        !           128: 
        !           129: /* If a prefix and a nexthop match any route in the routing table,
        !           130:    then return 1, otherwise return 0. */
        !           131: int
        !           132: ospf_route_match_same (struct route_table *rt, struct prefix_ipv4 *prefix,
        !           133:                       struct ospf_route *newor)
        !           134: {
        !           135:   struct route_node *rn;
        !           136:   struct ospf_route *or;
        !           137:   struct ospf_path *op;
        !           138:   struct ospf_path *newop;
        !           139:   struct listnode *n1;
        !           140:   struct listnode *n2;
        !           141: 
        !           142:   if (! rt || ! prefix)
        !           143:     return 0;
        !           144: 
        !           145:    rn = route_node_lookup (rt, (struct prefix *) prefix);
        !           146:    if (! rn || ! rn->info)
        !           147:      return 0;
        !           148:  
        !           149:    route_unlock_node (rn);
        !           150: 
        !           151:    or = rn->info;
        !           152:    if (or->type == newor->type && or->cost == newor->cost)
        !           153:      {
        !           154:        if (or->type == OSPF_DESTINATION_NETWORK)
        !           155:         {
        !           156:           if (or->paths->count != newor->paths->count)
        !           157:             return 0;
        !           158: 
        !           159:           /* Check each path. */
        !           160:           for (n1 = listhead (or->paths), n2 = listhead (newor->paths);
        !           161:                n1 && n2; n1 = listnextnode (n1), n2 = listnextnode (n2))
        !           162:             { 
        !           163:               op = listgetdata (n1);
        !           164:               newop = listgetdata (n2);
        !           165: 
        !           166:               if (! IPV4_ADDR_SAME (&op->nexthop, &newop->nexthop))
        !           167:                 return 0;
        !           168:               if (op->ifindex != newop->ifindex)
        !           169:                 return 0;
        !           170:             }
        !           171:           return 1;
        !           172:         }
        !           173:        else if (prefix_same (&rn->p, (struct prefix *) prefix))
        !           174:         return 1;
        !           175:      }
        !           176:   return 0;
        !           177: }
        !           178: 
        !           179: /* delete routes generated from AS-External routes if there is a inter/intra
        !           180:  * area route
        !           181:  */
        !           182: static void 
        !           183: ospf_route_delete_same_ext(struct route_table *external_routes,
        !           184:                      struct route_table *routes)
        !           185: {
        !           186:   struct route_node *rn,
        !           187:                     *ext_rn;
        !           188:   
        !           189:   if ( (external_routes == NULL) || (routes == NULL) )
        !           190:     return;
        !           191:   
        !           192:   /* Remove deleted routes */
        !           193:   for ( rn = route_top (routes); rn; rn = route_next (rn) )
        !           194:     {
        !           195:       if (rn && rn->info)
        !           196:         {
        !           197:           struct prefix_ipv4 *p = (struct prefix_ipv4 *)(&rn->p);
        !           198:           if ( (ext_rn = route_node_lookup (external_routes, (struct prefix *)p)) )
        !           199:             {
        !           200:               if (ext_rn->info)
        !           201:                 {
        !           202:                   ospf_zebra_delete (p, ext_rn->info);
        !           203:                   ospf_route_free( ext_rn->info);
        !           204:                   ext_rn->info = NULL;
        !           205:                 }
        !           206:               route_unlock_node (ext_rn);
        !           207:             }
        !           208:         }
        !           209:     }
        !           210: }
        !           211: 
        !           212: /* rt: Old, cmprt: New */
        !           213: static void
        !           214: ospf_route_delete_uniq (struct route_table *rt, struct route_table *cmprt)
        !           215: {
        !           216:   struct route_node *rn;
        !           217:   struct ospf_route *or;
        !           218: 
        !           219:   for (rn = route_top (rt); rn; rn = route_next (rn))
        !           220:     if ((or = rn->info) != NULL) 
        !           221:       if (or->path_type == OSPF_PATH_INTRA_AREA ||
        !           222:          or->path_type == OSPF_PATH_INTER_AREA)
        !           223:        {
        !           224:          if (or->type == OSPF_DESTINATION_NETWORK)
        !           225:            {
        !           226:              if (! ospf_route_match_same (cmprt, 
        !           227:                                           (struct prefix_ipv4 *) &rn->p, or))
        !           228:                ospf_zebra_delete ((struct prefix_ipv4 *) &rn->p, or);
        !           229:            }
        !           230:          else if (or->type == OSPF_DESTINATION_DISCARD)
        !           231:            if (! ospf_route_match_same (cmprt,
        !           232:                                         (struct prefix_ipv4 *) &rn->p, or))
        !           233:              ospf_zebra_delete_discard ((struct prefix_ipv4 *) &rn->p);
        !           234:        }
        !           235: }
        !           236: 
        !           237: /* Install routes to table. */
        !           238: void
        !           239: ospf_route_install (struct ospf *ospf, struct route_table *rt)
        !           240: {
        !           241:   struct route_node *rn;
        !           242:   struct ospf_route *or;
        !           243: 
        !           244:   /* rt contains new routing table, new_table contains an old one.
        !           245:      updating pointers */
        !           246:   if (ospf->old_table)
        !           247:     ospf_route_table_free (ospf->old_table);
        !           248: 
        !           249:   ospf->old_table = ospf->new_table;
        !           250:   ospf->new_table = rt;
        !           251: 
        !           252:   /* Delete old routes. */
        !           253:   if (ospf->old_table)
        !           254:     ospf_route_delete_uniq (ospf->old_table, rt);
        !           255:   if (ospf->old_external_route)
        !           256:     ospf_route_delete_same_ext (ospf->old_external_route, rt);
        !           257: 
        !           258:   /* Install new routes. */
        !           259:   for (rn = route_top (rt); rn; rn = route_next (rn))
        !           260:     if ((or = rn->info) != NULL)
        !           261:       {
        !           262:        if (or->type == OSPF_DESTINATION_NETWORK)
        !           263:          {
        !           264:            if (! ospf_route_match_same (ospf->old_table,
        !           265:                                         (struct prefix_ipv4 *)&rn->p, or))
        !           266:              ospf_zebra_add ((struct prefix_ipv4 *) &rn->p, or);
        !           267:          }
        !           268:        else if (or->type == OSPF_DESTINATION_DISCARD)
        !           269:          if (! ospf_route_match_same (ospf->old_table,
        !           270:                                       (struct prefix_ipv4 *) &rn->p, or))
        !           271:            ospf_zebra_add_discard ((struct prefix_ipv4 *) &rn->p);
        !           272:       }
        !           273: }
        !           274: 
        !           275: static void
        !           276: ospf_intra_route_add (struct route_table *rt, struct vertex *v,
        !           277:                      struct ospf_area *area)
        !           278: {
        !           279:   struct route_node *rn;
        !           280:   struct ospf_route *or;
        !           281:   struct prefix_ipv4 p;
        !           282:   struct ospf_path *path;
        !           283:   struct vertex_parent *parent;
        !           284:   struct listnode *node, *nnode;
        !           285: 
        !           286:   p.family = AF_INET;
        !           287:   p.prefix = v->id;
        !           288:   if (v->type == OSPF_VERTEX_ROUTER)
        !           289:     p.prefixlen = IPV4_MAX_BITLEN;
        !           290:   else
        !           291:     {
        !           292:       struct network_lsa *lsa = (struct network_lsa *) v->lsa;
        !           293:       p.prefixlen = ip_masklen (lsa->mask);
        !           294:     }
        !           295:   apply_mask_ipv4 (&p);
        !           296: 
        !           297:   rn = route_node_get (rt, (struct prefix *) &p);
        !           298:   if (rn->info)
        !           299:     {
        !           300:       zlog_warn ("Same routing information exists for %s", inet_ntoa (v->id));
        !           301:       route_unlock_node (rn);
        !           302:       return;
        !           303:     }
        !           304: 
        !           305:   or = ospf_route_new ();
        !           306: 
        !           307:   if (v->type == OSPF_VERTEX_NETWORK)
        !           308:     {
        !           309:       or->type = OSPF_DESTINATION_NETWORK;
        !           310: 
        !           311:       for (ALL_LIST_ELEMENTS (v->parents, node, nnode, parent))
        !           312:         {
        !           313:           path = ospf_path_new ();
        !           314:           path->nexthop = parent->nexthop->router;
        !           315:           listnode_add (or->paths, path);
        !           316:         }
        !           317:     }
        !           318:   else
        !           319:     or->type = OSPF_DESTINATION_ROUTER;
        !           320: 
        !           321:   or->id = v->id;
        !           322:   or->u.std.area_id = area->area_id;
        !           323:   or->u.std.external_routing= area->external_routing;
        !           324:   or->path_type = OSPF_PATH_INTRA_AREA;
        !           325:   or->cost = v->distance;
        !           326: 
        !           327:   rn->info = or;
        !           328: }
        !           329: 
        !           330: /* RFC2328 16.1. (4). For "router". */
        !           331: void
        !           332: ospf_intra_add_router (struct route_table *rt, struct vertex *v,
        !           333:                       struct ospf_area *area)
        !           334: {
        !           335:   struct route_node *rn;
        !           336:   struct ospf_route *or;
        !           337:   struct prefix_ipv4 p;
        !           338:   struct router_lsa *lsa;
        !           339: 
        !           340:   if (IS_DEBUG_OSPF_EVENT)
        !           341:     zlog_debug ("ospf_intra_add_router: Start");
        !           342: 
        !           343:   lsa = (struct router_lsa *) v->lsa;
        !           344: 
        !           345:   if (IS_DEBUG_OSPF_EVENT)
        !           346:     zlog_debug ("ospf_intra_add_router: LS ID: %s",
        !           347:               inet_ntoa (lsa->header.id));
        !           348:   
        !           349:   if (!OSPF_IS_AREA_BACKBONE(area))
        !           350:     ospf_vl_up_check (area, lsa->header.id, v);
        !           351: 
        !           352:   if (!CHECK_FLAG (lsa->flags, ROUTER_LSA_SHORTCUT))
        !           353:     area->shortcut_capability = 0;
        !           354: 
        !           355:   /* If the newly added vertex is an area border router or AS boundary
        !           356:      router, a routing table entry is added whose destination type is
        !           357:      "router". */
        !           358:   if (! IS_ROUTER_LSA_BORDER (lsa) && ! IS_ROUTER_LSA_EXTERNAL (lsa))
        !           359:     {
        !           360:       if (IS_DEBUG_OSPF_EVENT)
        !           361:        zlog_debug ("ospf_intra_add_router: "
        !           362:                   "this router is neither ASBR nor ABR, skipping it");
        !           363:       return;
        !           364:     }
        !           365: 
        !           366:   /* Update ABR and ASBR count in this area. */
        !           367:   if (IS_ROUTER_LSA_BORDER (lsa))
        !           368:     area->abr_count++;
        !           369:   if (IS_ROUTER_LSA_EXTERNAL (lsa))
        !           370:     area->asbr_count++;
        !           371: 
        !           372:   /* The Options field found in the associated router-LSA is copied
        !           373:      into the routing table entry's Optional capabilities field. Call
        !           374:      the newly added vertex Router X. */
        !           375:   or = ospf_route_new ();
        !           376: 
        !           377:   or->id = v->id;
        !           378:   or->u.std.area_id = area->area_id;
        !           379:   or->u.std.external_routing = area->external_routing;
        !           380:   or->path_type = OSPF_PATH_INTRA_AREA;
        !           381:   or->cost = v->distance;
        !           382:   or->type = OSPF_DESTINATION_ROUTER;
        !           383:   or->u.std.origin = (struct lsa_header *) lsa;
        !           384:   or->u.std.options = lsa->header.options;
        !           385:   or->u.std.flags = lsa->flags;
        !           386: 
        !           387:   /* If Router X is the endpoint of one of the calculating router's
        !           388:      virtual links, and the virtual link uses Area A as Transit area:
        !           389:      the virtual link is declared up, the IP address of the virtual
        !           390:      interface is set to the IP address of the outgoing interface
        !           391:      calculated above for Router X, and the virtual neighbor's IP
        !           392:      address is set to Router X's interface address (contained in
        !           393:      Router X's router-LSA) that points back to the root of the
        !           394:      shortest- path tree; equivalently, this is the interface that
        !           395:      points back to Router X's parent vertex on the shortest-path tree
        !           396:      (similar to the calculation in Section 16.1.1). */
        !           397: 
        !           398:   p.family = AF_INET;
        !           399:   p.prefix = v->id;
        !           400:   p.prefixlen = IPV4_MAX_BITLEN;
        !           401: 
        !           402:   if (IS_DEBUG_OSPF_EVENT)
        !           403:     zlog_debug ("ospf_intra_add_router: talking about %s/%d",
        !           404:               inet_ntoa (p.prefix), p.prefixlen);
        !           405: 
        !           406:   rn = route_node_get (rt, (struct prefix *) &p);
        !           407: 
        !           408:   /* Note that we keep all routes to ABRs and ASBRs, not only the best */
        !           409:   if (rn->info == NULL)
        !           410:     rn->info = list_new ();
        !           411:   else
        !           412:     route_unlock_node (rn);
        !           413: 
        !           414:   ospf_route_copy_nexthops_from_vertex (or, v);
        !           415: 
        !           416:   listnode_add (rn->info, or);
        !           417: 
        !           418:   if (IS_DEBUG_OSPF_EVENT)
        !           419:     zlog_debug ("ospf_intra_add_router: Stop");
        !           420: }
        !           421: 
        !           422: /* RFC2328 16.1. (4).  For transit network. */
        !           423: void
        !           424: ospf_intra_add_transit (struct route_table *rt, struct vertex *v,
        !           425:                        struct ospf_area *area)
        !           426: {
        !           427:   struct route_node *rn;
        !           428:   struct ospf_route *or;
        !           429:   struct prefix_ipv4 p;
        !           430:   struct network_lsa *lsa;
        !           431: 
        !           432:   lsa = (struct network_lsa*) v->lsa;
        !           433: 
        !           434:   /* If the newly added vertex is a transit network, the routing table
        !           435:      entry for the network is located.  The entry's Destination ID is
        !           436:      the IP network number, which can be obtained by masking the
        !           437:      Vertex ID (Link State ID) with its associated subnet mask (found
        !           438:      in the body of the associated network-LSA). */
        !           439:   p.family = AF_INET;
        !           440:   p.prefix = v->id;
        !           441:   p.prefixlen = ip_masklen (lsa->mask);
        !           442:   apply_mask_ipv4 (&p);
        !           443: 
        !           444:   rn = route_node_get (rt, (struct prefix *) &p);
        !           445: 
        !           446:   /* If the routing table entry already exists (i.e., there is already
        !           447:      an intra-area route to the destination installed in the routing
        !           448:      table), multiple vertices have mapped to the same IP network.
        !           449:      For example, this can occur when a new Designated Router is being
        !           450:      established.  In this case, the current routing table entry
        !           451:      should be overwritten if and only if the newly found path is just
        !           452:      as short and the current routing table entry's Link State Origin
        !           453:      has a smaller Link State ID than the newly added vertex' LSA. */
        !           454:   if (rn->info)
        !           455:     {
        !           456:       struct ospf_route *cur_or;
        !           457: 
        !           458:       route_unlock_node (rn);
        !           459:       cur_or = rn->info;
        !           460: 
        !           461:       if (v->distance > cur_or->cost ||
        !           462:           IPV4_ADDR_CMP (&cur_or->u.std.origin->id, &lsa->header.id) > 0)
        !           463:        return;
        !           464:       
        !           465:       ospf_route_free (rn->info);
        !           466:     }
        !           467: 
        !           468:   or = ospf_route_new ();
        !           469: 
        !           470:   or->id = v->id;
        !           471:   or->u.std.area_id = area->area_id;
        !           472:   or->u.std.external_routing = area->external_routing;
        !           473:   or->path_type = OSPF_PATH_INTRA_AREA;
        !           474:   or->cost = v->distance;
        !           475:   or->type = OSPF_DESTINATION_NETWORK;
        !           476:   or->u.std.origin = (struct lsa_header *) lsa;
        !           477: 
        !           478:   ospf_route_copy_nexthops_from_vertex (or, v);
        !           479:   
        !           480:   rn->info = or;
        !           481: }
        !           482: 
        !           483: /* RFC2328 16.1. second stage. */
        !           484: void
        !           485: ospf_intra_add_stub (struct route_table *rt, struct router_lsa_link *link,
        !           486:                     struct vertex *v, struct ospf_area *area,
        !           487:                     int parent_is_root)
        !           488: {
        !           489:   u_int32_t cost;
        !           490:   struct route_node *rn;
        !           491:   struct ospf_route *or;
        !           492:   struct prefix_ipv4 p;
        !           493:   struct router_lsa *lsa;
        !           494:   struct ospf_interface *oi;
        !           495:   struct ospf_path *path;
        !           496: 
        !           497:   if (IS_DEBUG_OSPF_EVENT)
        !           498:     zlog_debug ("ospf_intra_add_stub(): Start");
        !           499: 
        !           500:   lsa = (struct router_lsa *) v->lsa;
        !           501: 
        !           502:   p.family = AF_INET;
        !           503:   p.prefix = link->link_id;
        !           504:   p.prefixlen = ip_masklen (link->link_data);
        !           505:   apply_mask_ipv4 (&p);
        !           506: 
        !           507:   if (IS_DEBUG_OSPF_EVENT)
        !           508:     zlog_debug ("ospf_intra_add_stub(): processing route to %s/%d",  
        !           509:               inet_ntoa (p.prefix), p.prefixlen);
        !           510: 
        !           511:   /* (1) Calculate the distance D of stub network from the root.  D is
        !           512:      equal to the distance from the root to the router vertex
        !           513:      (calculated in stage 1), plus the stub network link's advertised
        !           514:      cost. */
        !           515:   cost = v->distance + ntohs (link->m[0].metric);
        !           516: 
        !           517:   if (IS_DEBUG_OSPF_EVENT)
        !           518:     zlog_debug ("ospf_intra_add_stub(): calculated cost is %d + %d = %d", 
        !           519:               v->distance, ntohs(link->m[0].metric), cost);
        !           520:   
        !           521:   /* PtP links with /32 masks adds host routes to remote, directly
        !           522:    * connected hosts, see RFC 2328, 12.4.1.1, Option 1.
        !           523:    * Such routes can just be ignored for the sake of tidyness.
        !           524:    */
        !           525:   if (parent_is_root && link->link_data.s_addr == 0xffffffff &&
        !           526:       ospf_if_lookup_by_local_addr (area->ospf, NULL, link->link_id))
        !           527:     {
        !           528:       if (IS_DEBUG_OSPF_EVENT)
        !           529:         zlog_debug ("%s: ignoring host route %s/32 to self.",
        !           530:                     __func__, inet_ntoa (link->link_id));
        !           531:       return;
        !           532:     }
        !           533:   
        !           534:   rn = route_node_get (rt, (struct prefix *) &p);
        !           535: 
        !           536:   /* Lookup current routing table. */
        !           537:   if (rn->info)
        !           538:     {
        !           539:       struct ospf_route *cur_or;
        !           540: 
        !           541:       route_unlock_node (rn);
        !           542: 
        !           543:       cur_or = rn->info;
        !           544: 
        !           545:       if (IS_DEBUG_OSPF_EVENT)
        !           546:        zlog_debug ("ospf_intra_add_stub(): "
        !           547:                   "another route to the same prefix found with cost %u",
        !           548:                   cur_or->cost);
        !           549: 
        !           550:       /* Compare this distance to the current best cost to the stub
        !           551:         network.  This is done by looking up the stub network's
        !           552:         current routing table entry.  If the calculated distance D is
        !           553:         larger, go on to examine the next stub network link in the
        !           554:         LSA. */
        !           555:       if (cost > cur_or->cost)
        !           556:        {
        !           557:          if (IS_DEBUG_OSPF_EVENT)
        !           558:            zlog_debug ("ospf_intra_add_stub(): old route is better, exit");
        !           559:          return;
        !           560:        }
        !           561: 
        !           562:       /* (2) If this step is reached, the stub network's routing table
        !           563:         entry must be updated.  Calculate the set of next hops that
        !           564:         would result from using the stub network link.  This
        !           565:         calculation is shown in Section 16.1.1; input to this
        !           566:         calculation is the destination (the stub network) and the
        !           567:         parent vertex (the router vertex). If the distance D is the
        !           568:         same as the current routing table cost, simply add this set
        !           569:         of next hops to the routing table entry's list of next hops.
        !           570:         In this case, the routing table already has a Link State
        !           571:         Origin.  If this Link State Origin is a router-LSA whose Link
        !           572:         State ID is smaller than V's Router ID, reset the Link State
        !           573:         Origin to V's router-LSA. */
        !           574: 
        !           575:       if (cost == cur_or->cost)
        !           576:        {
        !           577:          if (IS_DEBUG_OSPF_EVENT)
        !           578:            zlog_debug ("ospf_intra_add_stub(): routes are equal, merge");
        !           579: 
        !           580:          ospf_route_copy_nexthops_from_vertex (cur_or, v);
        !           581: 
        !           582:          if (IPV4_ADDR_CMP (&cur_or->u.std.origin->id, &lsa->header.id) < 0)
        !           583:            cur_or->u.std.origin = (struct lsa_header *) lsa;
        !           584:          return;
        !           585:        }
        !           586: 
        !           587:       /* Otherwise D is smaller than the routing table cost.
        !           588:         Overwrite the current routing table entry by setting the
        !           589:         routing table entry's cost to D, and by setting the entry's
        !           590:         list of next hops to the newly calculated set.  Set the
        !           591:         routing table entry's Link State Origin to V's router-LSA.
        !           592:         Then go on to examine the next stub network link. */
        !           593: 
        !           594:       if (cost < cur_or->cost)
        !           595:        {
        !           596:          if (IS_DEBUG_OSPF_EVENT)
        !           597:            zlog_debug ("ospf_intra_add_stub(): new route is better, set it");
        !           598: 
        !           599:          cur_or->cost = cost;
        !           600: 
        !           601:          list_delete_all_node (cur_or->paths);
        !           602: 
        !           603:          ospf_route_copy_nexthops_from_vertex (cur_or, v);
        !           604: 
        !           605:          cur_or->u.std.origin = (struct lsa_header *) lsa;
        !           606:          return;
        !           607:        }
        !           608:     }
        !           609: 
        !           610:   if (IS_DEBUG_OSPF_EVENT)
        !           611:     zlog_debug ("ospf_intra_add_stub(): installing new route");
        !           612: 
        !           613:   or = ospf_route_new ();
        !           614: 
        !           615:   or->id = v->id;
        !           616:   or->u.std.area_id = area->area_id;
        !           617:   or->u.std.external_routing = area->external_routing;
        !           618:   or->path_type = OSPF_PATH_INTRA_AREA;
        !           619:   or->cost = cost;
        !           620:   or->type = OSPF_DESTINATION_NETWORK;
        !           621:   or->u.std.origin = (struct lsa_header *) lsa;
        !           622: 
        !           623:   /* Nexthop is depend on connection type. */
        !           624:   if (v != area->spf)
        !           625:     {
        !           626:       if (IS_DEBUG_OSPF_EVENT)
        !           627:        zlog_debug ("ospf_intra_add_stub(): this network is on remote router");
        !           628:       ospf_route_copy_nexthops_from_vertex (or, v);
        !           629:     }
        !           630:   else
        !           631:     {
        !           632:       if (IS_DEBUG_OSPF_EVENT)
        !           633:        zlog_debug ("ospf_intra_add_stub(): this network is on this router");
        !           634: 
        !           635:       if ((oi = ospf_if_lookup_by_prefix (area->ospf, &p)))
        !           636:        {
        !           637:          if (IS_DEBUG_OSPF_EVENT)
        !           638:            zlog_debug ("ospf_intra_add_stub(): the interface is %s",
        !           639:                       IF_NAME (oi));
        !           640: 
        !           641:          path = ospf_path_new ();
        !           642:          path->nexthop.s_addr = 0;
        !           643:          path->ifindex = oi->ifp->ifindex;
        !           644:          listnode_add (or->paths, path);
        !           645:        }
        !           646:       else
        !           647:        {
        !           648:          if (IS_DEBUG_OSPF_EVENT)
        !           649:            zlog_debug ("ospf_intra_add_stub(): where's the interface ?");
        !           650:        }
        !           651:     }
        !           652: 
        !           653:   rn->info = or;
        !           654: 
        !           655:   if (IS_DEBUG_OSPF_EVENT)
        !           656:     zlog_debug("ospf_intra_add_stub(): Stop");
        !           657: }
        !           658: 
        !           659: const char *ospf_path_type_str[] =
        !           660: {
        !           661:   "unknown-type",
        !           662:   "intra-area",
        !           663:   "inter-area",
        !           664:   "type1-external",
        !           665:   "type2-external"
        !           666: };
        !           667: 
        !           668: void
        !           669: ospf_route_table_dump (struct route_table *rt)
        !           670: {
        !           671:   struct route_node *rn;
        !           672:   struct ospf_route *or;
        !           673:   char buf1[BUFSIZ];
        !           674:   char buf2[BUFSIZ];
        !           675:   struct listnode *pnode;
        !           676:   struct ospf_path *path;
        !           677: 
        !           678: #if 0
        !           679:   zlog_debug ("Type   Dest   Area   Path        Type    Cost   Next     Adv.");
        !           680:   zlog_debug ("                                        Hop(s)   Router(s)");
        !           681: #endif /* 0 */
        !           682: 
        !           683:   zlog_debug ("========== OSPF routing table ==========");
        !           684:   for (rn = route_top (rt); rn; rn = route_next (rn))
        !           685:     if ((or = rn->info) != NULL)
        !           686:       {
        !           687:         if (or->type == OSPF_DESTINATION_NETWORK)
        !           688:          {
        !           689:            zlog_debug ("N %s/%d\t%s\t%s\t%d", 
        !           690:                       inet_ntop (AF_INET, &rn->p.u.prefix4, buf1, BUFSIZ),
        !           691:                       rn->p.prefixlen,
        !           692:                       inet_ntop (AF_INET, &or->u.std.area_id, buf2,
        !           693:                                  BUFSIZ),
        !           694:                       ospf_path_type_str[or->path_type],
        !           695:                       or->cost);
        !           696:            for (ALL_LIST_ELEMENTS_RO (or->paths, pnode, path))
        !           697:               zlog_debug ("  -> %s", inet_ntoa (path->nexthop));
        !           698:          }
        !           699:         else
        !           700:          zlog_debug ("R %s\t%s\t%s\t%d", 
        !           701:                     inet_ntop (AF_INET, &rn->p.u.prefix4, buf1, BUFSIZ),
        !           702:                     inet_ntop (AF_INET, &or->u.std.area_id, buf2,
        !           703:                                BUFSIZ),
        !           704:                     ospf_path_type_str[or->path_type],
        !           705:                     or->cost);
        !           706:       }
        !           707:   zlog_debug ("========================================");
        !           708: }
        !           709: 
        !           710: /* This is 16.4.1 implementation.
        !           711:    o Intra-area paths using non-backbone areas are always the most preferred.
        !           712:    o The other paths, intra-area backbone paths and inter-area paths,
        !           713:      are of equal preference. */
        !           714: static int
        !           715: ospf_asbr_route_cmp (struct ospf *ospf, struct ospf_route *r1,
        !           716:                     struct ospf_route *r2)
        !           717: {
        !           718:   u_char r1_type, r2_type;
        !           719: 
        !           720:   r1_type = r1->path_type;
        !           721:   r2_type = r2->path_type;
        !           722: 
        !           723:   /* r1/r2 itself is backbone, and it's Inter-area path. */
        !           724:   if (OSPF_IS_AREA_ID_BACKBONE (r1->u.std.area_id))
        !           725:     r1_type = OSPF_PATH_INTER_AREA;
        !           726:   if (OSPF_IS_AREA_ID_BACKBONE (r2->u.std.area_id))
        !           727:     r2_type = OSPF_PATH_INTER_AREA;
        !           728: 
        !           729:   return (r1_type - r2_type);
        !           730: }
        !           731: 
        !           732: /* Compare two routes.
        !           733:  ret <  0 -- r1 is better.
        !           734:  ret == 0 -- r1 and r2 are the same.
        !           735:  ret >  0 -- r2 is better. */
        !           736: int
        !           737: ospf_route_cmp (struct ospf *ospf, struct ospf_route *r1,
        !           738:                struct ospf_route *r2)
        !           739: {
        !           740:   int ret = 0;
        !           741: 
        !           742:   /* Path types of r1 and r2 are not the same. */
        !           743:   if ((ret = (r1->path_type - r2->path_type)))
        !           744:     return ret;
        !           745: 
        !           746:   if (IS_DEBUG_OSPF_EVENT)
        !           747:     zlog_debug ("Route[Compare]: Path types are the same.");
        !           748:   /* Path types are the same, compare any cost. */
        !           749:   switch (r1->path_type)
        !           750:     {
        !           751:     case OSPF_PATH_INTRA_AREA:
        !           752:     case OSPF_PATH_INTER_AREA:
        !           753:       break;
        !           754:     case OSPF_PATH_TYPE1_EXTERNAL:
        !           755:       if (!CHECK_FLAG (ospf->config, OSPF_RFC1583_COMPATIBLE))
        !           756:        {
        !           757:          ret = ospf_asbr_route_cmp (ospf, r1->u.ext.asbr, r2->u.ext.asbr);
        !           758:          if (ret != 0)
        !           759:            return ret;
        !           760:        }
        !           761:       break;
        !           762:     case OSPF_PATH_TYPE2_EXTERNAL:
        !           763:       if ((ret = (r1->u.ext.type2_cost - r2->u.ext.type2_cost)))
        !           764:        return ret;
        !           765: 
        !           766:       if (!CHECK_FLAG (ospf->config, OSPF_RFC1583_COMPATIBLE))
        !           767:        {
        !           768:          ret = ospf_asbr_route_cmp (ospf, r1->u.ext.asbr, r2->u.ext.asbr);
        !           769:          if (ret != 0)
        !           770:            return ret;
        !           771:        }
        !           772:       break;
        !           773:     }      
        !           774: 
        !           775:   /* Anyway, compare the costs. */
        !           776:   return (r1->cost - r2->cost);
        !           777: }
        !           778: 
        !           779: static int
        !           780: ospf_path_exist (struct list *plist, struct in_addr nexthop,
        !           781:                 struct ospf_interface *oi)
        !           782: {
        !           783:   struct listnode *node, *nnode;
        !           784:   struct ospf_path *path;
        !           785: 
        !           786:   for (ALL_LIST_ELEMENTS (plist, node, nnode, path))
        !           787:     if (IPV4_ADDR_SAME (&path->nexthop, &nexthop) &&
        !           788:        path->ifindex == oi->ifp->ifindex)
        !           789:       return 1;
        !           790: 
        !           791:   return 0;
        !           792: }
        !           793: 
        !           794: void
        !           795: ospf_route_copy_nexthops_from_vertex (struct ospf_route *to,
        !           796:                                      struct vertex *v)
        !           797: {
        !           798:   struct listnode *node;
        !           799:   struct ospf_path *path;
        !           800:   struct vertex_nexthop *nexthop;
        !           801:   struct vertex_parent *vp;
        !           802: 
        !           803:   assert (to->paths);
        !           804: 
        !           805:   for (ALL_LIST_ELEMENTS_RO (v->parents, node, vp))
        !           806:     {
        !           807:       nexthop = vp->nexthop;
        !           808:       
        !           809:       if (nexthop->oi != NULL) 
        !           810:        {
        !           811:          if (! ospf_path_exist (to->paths, nexthop->router, nexthop->oi))
        !           812:            {
        !           813:              path = ospf_path_new ();
        !           814:              path->nexthop = nexthop->router;
        !           815:              path->ifindex = nexthop->oi->ifp->ifindex;
        !           816:              listnode_add (to->paths, path);
        !           817:            }
        !           818:        }
        !           819:     }
        !           820: }
        !           821: 
        !           822: struct ospf_path *
        !           823: ospf_path_lookup (struct list *plist, struct ospf_path *path)
        !           824: {
        !           825:   struct listnode *node;
        !           826:   struct ospf_path *op;
        !           827: 
        !           828:   for (ALL_LIST_ELEMENTS_RO (plist, node, op))
        !           829:   {
        !           830:     if (!IPV4_ADDR_SAME (&op->nexthop, &path->nexthop))
        !           831:       continue;
        !           832:     if (!IPV4_ADDR_SAME (&op->adv_router, &path->adv_router))
        !           833:       continue;
        !           834:     if (op->ifindex != path->ifindex)
        !           835:       continue;
        !           836:     return op;
        !           837:   }
        !           838:   return NULL;
        !           839: }
        !           840: 
        !           841: void
        !           842: ospf_route_copy_nexthops (struct ospf_route *to, struct list *from)
        !           843: {
        !           844:   struct listnode *node, *nnode;
        !           845:   struct ospf_path *path;
        !           846: 
        !           847:   assert (to->paths);
        !           848: 
        !           849:   for (ALL_LIST_ELEMENTS (from, node, nnode, path))
        !           850:     /* The same routes are just discarded. */
        !           851:     if (!ospf_path_lookup (to->paths, path))
        !           852:       listnode_add (to->paths, ospf_path_dup (path));
        !           853: }
        !           854: 
        !           855: void
        !           856: ospf_route_subst_nexthops (struct ospf_route *to, struct list *from)
        !           857: {
        !           858: 
        !           859:   list_delete_all_node (to->paths);
        !           860:   ospf_route_copy_nexthops (to, from);
        !           861: }
        !           862: 
        !           863: void
        !           864: ospf_route_subst (struct route_node *rn, struct ospf_route *new_or,
        !           865:                  struct ospf_route *over)
        !           866: {
        !           867:   route_lock_node (rn);
        !           868:   ospf_route_free (rn->info);
        !           869: 
        !           870:   ospf_route_copy_nexthops (new_or, over->paths);
        !           871:   rn->info = new_or;
        !           872:   route_unlock_node (rn);
        !           873: }
        !           874: 
        !           875: void
        !           876: ospf_route_add (struct route_table *rt, struct prefix_ipv4 *p,
        !           877:                struct ospf_route *new_or, struct ospf_route *over)
        !           878: {
        !           879:   struct route_node *rn;
        !           880: 
        !           881:   rn = route_node_get (rt, (struct prefix *) p);
        !           882: 
        !           883:   ospf_route_copy_nexthops (new_or, over->paths);
        !           884: 
        !           885:   if (rn->info)
        !           886:     {
        !           887:       if (IS_DEBUG_OSPF_EVENT)
        !           888:        zlog_debug ("ospf_route_add(): something's wrong !");
        !           889:       route_unlock_node (rn);
        !           890:       return;
        !           891:     }
        !           892: 
        !           893:   rn->info = new_or;
        !           894: }
        !           895: 
        !           896: void
        !           897: ospf_prune_unreachable_networks (struct route_table *rt)
        !           898: {
        !           899:   struct route_node *rn, *next;
        !           900:   struct ospf_route *or;
        !           901: 
        !           902:   if (IS_DEBUG_OSPF_EVENT)
        !           903:     zlog_debug ("Pruning unreachable networks");
        !           904: 
        !           905:   for (rn = route_top (rt); rn; rn = next)
        !           906:     {
        !           907:       next = route_next (rn);
        !           908:       if (rn->info != NULL)
        !           909:        {
        !           910:          or = rn->info;
        !           911:          if (listcount (or->paths) == 0)
        !           912:            {
        !           913:              if (IS_DEBUG_OSPF_EVENT)
        !           914:                zlog_debug ("Pruning route to %s/%d",
        !           915:                           inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen);
        !           916: 
        !           917:              ospf_route_free (or);
        !           918:              rn->info = NULL;
        !           919:              route_unlock_node (rn);
        !           920:            }
        !           921:        }
        !           922:     }
        !           923: }
        !           924: 
        !           925: void
        !           926: ospf_prune_unreachable_routers (struct route_table *rtrs)
        !           927: {
        !           928:   struct route_node *rn, *next;
        !           929:   struct ospf_route *or;
        !           930:   struct listnode *node, *nnode;
        !           931:   struct list *paths;
        !           932: 
        !           933:   if (IS_DEBUG_OSPF_EVENT)
        !           934:     zlog_debug ("Pruning unreachable routers");
        !           935: 
        !           936:   for (rn = route_top (rtrs); rn; rn = next)
        !           937:     {
        !           938:       next = route_next (rn);
        !           939:       if ((paths = rn->info) == NULL)
        !           940:        continue;
        !           941: 
        !           942:       for (ALL_LIST_ELEMENTS (paths, node, nnode, or))
        !           943:        {
        !           944:          if (listcount (or->paths) == 0)
        !           945:            {
        !           946:              if (IS_DEBUG_OSPF_EVENT)
        !           947:                {
        !           948:                  zlog_debug ("Pruning route to rtr %s",
        !           949:                             inet_ntoa (rn->p.u.prefix4));
        !           950:                  zlog_debug ("               via area %s",
        !           951:                             inet_ntoa (or->u.std.area_id));
        !           952:                }
        !           953: 
        !           954:              listnode_delete (paths, or);
        !           955:              ospf_route_free (or);
        !           956:            }
        !           957:        }
        !           958: 
        !           959:       if (listcount (paths) == 0)
        !           960:        {
        !           961:          if (IS_DEBUG_OSPF_EVENT)
        !           962:            zlog_debug ("Pruning router node %s", inet_ntoa (rn->p.u.prefix4));
        !           963: 
        !           964:          list_delete (paths);
        !           965:          rn->info = NULL;
        !           966:          route_unlock_node (rn);
        !           967:        }
        !           968:     }
        !           969: }
        !           970: 
        !           971: int
        !           972: ospf_add_discard_route (struct route_table *rt, struct ospf_area *area,
        !           973:                        struct prefix_ipv4 *p)
        !           974: {
        !           975:   struct route_node *rn;
        !           976:   struct ospf_route *or, *new_or;
        !           977: 
        !           978:   rn = route_node_get (rt, (struct prefix *) p);
        !           979: 
        !           980:   if (rn == NULL)
        !           981:     {
        !           982:       if (IS_DEBUG_OSPF_EVENT)
        !           983:        zlog_debug ("ospf_add_discard_route(): router installation error");
        !           984:       return 0;
        !           985:     }
        !           986: 
        !           987:   if (rn->info) /* If the route to the same destination is found */
        !           988:     {
        !           989:       route_unlock_node (rn);
        !           990: 
        !           991:       or = rn->info;
        !           992: 
        !           993:       if (or->path_type == OSPF_PATH_INTRA_AREA)
        !           994:        {
        !           995:          if (IS_DEBUG_OSPF_EVENT)
        !           996:            zlog_debug ("ospf_add_discard_route(): "
        !           997:                       "an intra-area route exists");
        !           998:          return 0;
        !           999:        }
        !          1000: 
        !          1001:       if (or->type == OSPF_DESTINATION_DISCARD)
        !          1002:        {
        !          1003:          if (IS_DEBUG_OSPF_EVENT)
        !          1004:            zlog_debug ("ospf_add_discard_route(): "
        !          1005:                       "discard entry already installed");
        !          1006:          return 0;
        !          1007:        }
        !          1008: 
        !          1009:       ospf_route_free (rn->info);
        !          1010:   }
        !          1011: 
        !          1012:   new_or = ospf_route_new ();
        !          1013:   new_or->type = OSPF_DESTINATION_DISCARD;
        !          1014:   new_or->id.s_addr = 0;
        !          1015:   new_or->cost = 0;
        !          1016:   new_or->u.std.area_id = area->area_id;
        !          1017:   new_or->u.std.external_routing = area->external_routing;
        !          1018:   new_or->path_type = OSPF_PATH_INTER_AREA;
        !          1019:   rn->info = new_or;
        !          1020: 
        !          1021:   ospf_zebra_add_discard (p);
        !          1022: 
        !          1023:   return 1;
        !          1024: }
        !          1025: 
        !          1026: void
        !          1027: ospf_delete_discard_route (struct prefix_ipv4 *p)
        !          1028: {
        !          1029:   ospf_zebra_delete_discard(p);
        !          1030: }
        !          1031: 

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