ospf_route.c
上传用户:xiaozhuqw
上传日期:2009-11-15
资源大小:1338k
文件大小:25k
源码类别:

网络

开发平台:

Unix_Linux

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