+ initial edition of meta-queue for RIB updates processing (bug #431)
[jleu-quagga.git] / ospfd / ospf_route.c
blob3a1fa9992445fc09a23035f9332abbb5cee9efc2
1 /*
2 * OSPF routing table.
3 * Copyright (C) 1999, 2000 Toshiaki Takada
5 * This file is part of GNU Zebra.
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.
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.
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.
23 #include <zebra.h>
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"
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"
43 struct ospf_route *
44 ospf_route_new ()
46 struct ospf_route *new;
48 new = XCALLOC (MTYPE_OSPF_ROUTE, sizeof (struct ospf_route));
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;
55 return new;
58 void
59 ospf_route_free (struct ospf_route *or)
61 if (or->paths)
62 list_delete (or->paths);
64 XFREE (MTYPE_OSPF_ROUTE, or);
67 struct ospf_path *
68 ospf_path_new ()
70 struct ospf_path *new;
72 new = XCALLOC (MTYPE_OSPF_PATH, sizeof (struct ospf_path));
74 return new;
77 static struct ospf_path *
78 ospf_path_dup (struct ospf_path *path)
80 struct ospf_path *new;
82 new = ospf_path_new ();
83 memcpy (new, path, sizeof (struct ospf_path));
85 return new;
88 void
89 ospf_path_free (struct ospf_path *op)
91 XFREE (MTYPE_OSPF_PATH, op);
94 void
95 ospf_route_delete (struct route_table *rt)
97 struct route_node *rn;
98 struct ospf_route *or;
100 for (rn = route_top (rt); rn; rn = route_next (rn))
101 if ((or = rn->info) != NULL)
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);
111 void
112 ospf_route_table_free (struct route_table *rt)
114 struct route_node *rn;
115 struct ospf_route *or;
117 for (rn = route_top (rt); rn; rn = route_next (rn))
118 if ((or = rn->info) != NULL)
120 ospf_route_free (or);
122 rn->info = NULL;
123 route_unlock_node (rn);
126 route_table_finish (rt);
129 /* If a prefix and a nexthop match any route in the routing table,
130 then return 1, otherwise return 0. */
132 ospf_route_match_same (struct route_table *rt, struct prefix_ipv4 *prefix,
133 struct ospf_route *newor)
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;
142 if (! rt || ! prefix)
143 return 0;
145 rn = route_node_lookup (rt, (struct prefix *) prefix);
146 if (! rn || ! rn->info)
147 return 0;
149 route_unlock_node (rn);
151 or = rn->info;
152 if (or->type == newor->type && or->cost == newor->cost)
154 if (or->type == OSPF_DESTINATION_NETWORK)
156 if (or->paths->count != newor->paths->count)
157 return 0;
159 /* Check each path. */
160 for (n1 = listhead (or->paths), n2 = listhead (newor->paths);
161 n1 && n2; n1 = listnextnode (n1), n2 = listnextnode (n2))
163 op = listgetdata (n1);
164 newop = listgetdata (n2);
166 if (! IPV4_ADDR_SAME (&op->nexthop, &newop->nexthop))
167 return 0;
169 return 1;
171 else if (prefix_same (&rn->p, (struct prefix *) prefix))
172 return 1;
174 return 0;
177 /* delete routes generated from AS-External routes if there is a inter/intra
178 * area route
180 static void
181 ospf_route_delete_same_ext(struct route_table *external_routes,
182 struct route_table *routes)
184 struct route_node *rn,
185 *ext_rn;
187 if ( (external_routes == NULL) || (routes == NULL) )
188 return;
190 /* Remove deleted routes */
191 for ( rn = route_top (routes); rn; rn = route_next (rn) )
193 if (rn && rn->info)
195 struct prefix_ipv4 *p = (struct prefix_ipv4 *)(&rn->p);
196 if ( (ext_rn = route_node_lookup (external_routes, (struct prefix *)p)) )
198 if (ext_rn->info)
200 ospf_zebra_delete (p, ext_rn->info);
201 ospf_route_free( ext_rn->info);
202 ext_rn->info = NULL;
204 route_unlock_node (ext_rn);
210 /* rt: Old, cmprt: New */
211 static void
212 ospf_route_delete_uniq (struct route_table *rt, struct route_table *cmprt)
214 struct route_node *rn;
215 struct ospf_route *or;
217 for (rn = route_top (rt); rn; rn = route_next (rn))
218 if ((or = rn->info) != NULL)
219 if (or->path_type == OSPF_PATH_INTRA_AREA ||
220 or->path_type == OSPF_PATH_INTER_AREA)
222 if (or->type == OSPF_DESTINATION_NETWORK)
224 if (! ospf_route_match_same (cmprt,
225 (struct prefix_ipv4 *) &rn->p, or))
226 ospf_zebra_delete ((struct prefix_ipv4 *) &rn->p, or);
228 else if (or->type == OSPF_DESTINATION_DISCARD)
229 if (! ospf_route_match_same (cmprt,
230 (struct prefix_ipv4 *) &rn->p, or))
231 ospf_zebra_delete_discard ((struct prefix_ipv4 *) &rn->p);
235 /* Install routes to table. */
236 void
237 ospf_route_install (struct ospf *ospf, struct route_table *rt)
239 struct route_node *rn;
240 struct ospf_route *or;
242 /* rt contains new routing table, new_table contains an old one.
243 updating pointers */
244 if (ospf->old_table)
245 ospf_route_table_free (ospf->old_table);
247 ospf->old_table = ospf->new_table;
248 ospf->new_table = rt;
250 /* Delete old routes. */
251 if (ospf->old_table)
252 ospf_route_delete_uniq (ospf->old_table, rt);
253 if (ospf->old_external_route)
254 ospf_route_delete_same_ext (ospf->old_external_route, rt);
256 /* Install new routes. */
257 for (rn = route_top (rt); rn; rn = route_next (rn))
258 if ((or = rn->info) != NULL)
260 if (or->type == OSPF_DESTINATION_NETWORK)
262 if (! ospf_route_match_same (ospf->old_table,
263 (struct prefix_ipv4 *)&rn->p, or))
264 ospf_zebra_add ((struct prefix_ipv4 *) &rn->p, or);
266 else if (or->type == OSPF_DESTINATION_DISCARD)
267 if (! ospf_route_match_same (ospf->old_table,
268 (struct prefix_ipv4 *) &rn->p, or))
269 ospf_zebra_add_discard ((struct prefix_ipv4 *) &rn->p);
273 static void
274 ospf_intra_route_add (struct route_table *rt, struct vertex *v,
275 struct ospf_area *area)
277 struct route_node *rn;
278 struct ospf_route *or;
279 struct prefix_ipv4 p;
280 struct ospf_path *path;
281 struct vertex_parent *parent;
282 struct listnode *node, *nnode;
284 p.family = AF_INET;
285 p.prefix = v->id;
286 if (v->type == OSPF_VERTEX_ROUTER)
287 p.prefixlen = IPV4_MAX_BITLEN;
288 else
290 struct network_lsa *lsa = (struct network_lsa *) v->lsa;
291 p.prefixlen = ip_masklen (lsa->mask);
293 apply_mask_ipv4 (&p);
295 rn = route_node_get (rt, (struct prefix *) &p);
296 if (rn->info)
298 zlog_warn ("Same routing information exists for %s", inet_ntoa (v->id));
299 route_unlock_node (rn);
300 return;
303 or = ospf_route_new ();
305 if (v->type == OSPF_VERTEX_NETWORK)
307 or->type = OSPF_DESTINATION_NETWORK;
309 for (ALL_LIST_ELEMENTS (v->parents, node, nnode, parent))
311 path = ospf_path_new ();
312 path->nexthop = parent->nexthop->router;
313 listnode_add (or->paths, path);
316 else
317 or->type = OSPF_DESTINATION_ROUTER;
319 or->id = v->id;
320 or->u.std.area_id = area->area_id;
321 or->u.std.external_routing= area->external_routing;
322 or->path_type = OSPF_PATH_INTRA_AREA;
323 or->cost = v->distance;
325 rn->info = or;
328 /* RFC2328 16.1. (4). For "router". */
329 void
330 ospf_intra_add_router (struct route_table *rt, struct vertex *v,
331 struct ospf_area *area)
333 struct route_node *rn;
334 struct ospf_route *or;
335 struct prefix_ipv4 p;
336 struct router_lsa *lsa;
338 if (IS_DEBUG_OSPF_EVENT)
339 zlog_debug ("ospf_intra_add_router: Start");
341 lsa = (struct router_lsa *) v->lsa;
343 if (IS_DEBUG_OSPF_EVENT)
344 zlog_debug ("ospf_intra_add_router: LS ID: %s",
345 inet_ntoa (lsa->header.id));
347 if (!OSPF_IS_AREA_BACKBONE(area))
348 ospf_vl_up_check (area, lsa->header.id, v);
350 if (!CHECK_FLAG (lsa->flags, ROUTER_LSA_SHORTCUT))
351 area->shortcut_capability = 0;
353 /* If the newly added vertex is an area border router or AS boundary
354 router, a routing table entry is added whose destination type is
355 "router". */
356 if (! IS_ROUTER_LSA_BORDER (lsa) && ! IS_ROUTER_LSA_EXTERNAL (lsa))
358 if (IS_DEBUG_OSPF_EVENT)
359 zlog_debug ("ospf_intra_add_router: "
360 "this router is neither ASBR nor ABR, skipping it");
361 return;
364 /* Update ABR and ASBR count in this area. */
365 if (IS_ROUTER_LSA_BORDER (lsa))
366 area->abr_count++;
367 if (IS_ROUTER_LSA_EXTERNAL (lsa))
368 area->asbr_count++;
370 /* The Options field found in the associated router-LSA is copied
371 into the routing table entry's Optional capabilities field. Call
372 the newly added vertex Router X. */
373 or = ospf_route_new ();
375 or->id = v->id;
376 or->u.std.area_id = area->area_id;
377 or->u.std.external_routing = area->external_routing;
378 or->path_type = OSPF_PATH_INTRA_AREA;
379 or->cost = v->distance;
380 or->type = OSPF_DESTINATION_ROUTER;
381 or->u.std.origin = (struct lsa_header *) lsa;
382 or->u.std.options = lsa->header.options;
383 or->u.std.flags = lsa->flags;
385 /* If Router X is the endpoint of one of the calculating router's
386 virtual links, and the virtual link uses Area A as Transit area:
387 the virtual link is declared up, the IP address of the virtual
388 interface is set to the IP address of the outgoing interface
389 calculated above for Router X, and the virtual neighbor's IP
390 address is set to Router X's interface address (contained in
391 Router X's router-LSA) that points back to the root of the
392 shortest- path tree; equivalently, this is the interface that
393 points back to Router X's parent vertex on the shortest-path tree
394 (similar to the calculation in Section 16.1.1). */
396 p.family = AF_INET;
397 p.prefix = v->id;
398 p.prefixlen = IPV4_MAX_BITLEN;
400 if (IS_DEBUG_OSPF_EVENT)
401 zlog_debug ("ospf_intra_add_router: talking about %s/%d",
402 inet_ntoa (p.prefix), p.prefixlen);
404 rn = route_node_get (rt, (struct prefix *) &p);
406 /* Note that we keep all routes to ABRs and ASBRs, not only the best */
407 if (rn->info == NULL)
408 rn->info = list_new ();
409 else
410 route_unlock_node (rn);
412 ospf_route_copy_nexthops_from_vertex (or, v);
414 listnode_add (rn->info, or);
416 if (IS_DEBUG_OSPF_EVENT)
417 zlog_debug ("ospf_intra_add_router: Stop");
420 /* RFC2328 16.1. (4). For transit network. */
421 void
422 ospf_intra_add_transit (struct route_table *rt, struct vertex *v,
423 struct ospf_area *area)
425 struct route_node *rn;
426 struct ospf_route *or;
427 struct prefix_ipv4 p;
428 struct network_lsa *lsa;
430 lsa = (struct network_lsa*) v->lsa;
432 /* If the newly added vertex is a transit network, the routing table
433 entry for the network is located. The entry's Destination ID is
434 the IP network number, which can be obtained by masking the
435 Vertex ID (Link State ID) with its associated subnet mask (found
436 in the body of the associated network-LSA). */
437 p.family = AF_INET;
438 p.prefix = v->id;
439 p.prefixlen = ip_masklen (lsa->mask);
440 apply_mask_ipv4 (&p);
442 rn = route_node_get (rt, (struct prefix *) &p);
444 /* If the routing table entry already exists (i.e., there is already
445 an intra-area route to the destination installed in the routing
446 table), multiple vertices have mapped to the same IP network.
447 For example, this can occur when a new Designated Router is being
448 established. In this case, the current routing table entry
449 should be overwritten if and only if the newly found path is just
450 as short and the current routing table entry's Link State Origin
451 has a smaller Link State ID than the newly added vertex' LSA. */
452 if (rn->info)
454 struct ospf_route *cur_or;
456 route_unlock_node (rn);
457 cur_or = rn->info;
459 if (v->distance > cur_or->cost ||
460 IPV4_ADDR_CMP (&cur_or->u.std.origin->id, &lsa->header.id) > 0)
461 return;
463 ospf_route_free (rn->info);
466 or = ospf_route_new ();
468 or->id = v->id;
469 or->u.std.area_id = area->area_id;
470 or->u.std.external_routing = area->external_routing;
471 or->path_type = OSPF_PATH_INTRA_AREA;
472 or->cost = v->distance;
473 or->type = OSPF_DESTINATION_NETWORK;
474 or->u.std.origin = (struct lsa_header *) lsa;
476 ospf_route_copy_nexthops_from_vertex (or, v);
478 rn->info = or;
481 /* RFC2328 16.1. second stage. */
482 void
483 ospf_intra_add_stub (struct route_table *rt, struct router_lsa_link *link,
484 struct vertex *v, struct ospf_area *area)
486 u_int32_t cost;
487 struct route_node *rn;
488 struct ospf_route *or;
489 struct prefix_ipv4 p;
490 struct router_lsa *lsa;
491 struct ospf_interface *oi;
492 struct ospf_path *path;
494 if (IS_DEBUG_OSPF_EVENT)
495 zlog_debug ("ospf_intra_add_stub(): Start");
497 lsa = (struct router_lsa *) v->lsa;
499 p.family = AF_INET;
500 p.prefix = link->link_id;
501 p.prefixlen = ip_masklen (link->link_data);
502 apply_mask_ipv4 (&p);
504 if (IS_DEBUG_OSPF_EVENT)
505 zlog_debug ("ospf_intra_add_stub(): processing route to %s/%d",
506 inet_ntoa (p.prefix), p.prefixlen);
508 /* (1) Calculate the distance D of stub network from the root. D is
509 equal to the distance from the root to the router vertex
510 (calculated in stage 1), plus the stub network link's advertised
511 cost. */
512 cost = v->distance + ntohs (link->m[0].metric);
514 if (IS_DEBUG_OSPF_EVENT)
515 zlog_debug ("ospf_intra_add_stub(): calculated cost is %d + %d = %d",
516 v->distance, ntohs(link->m[0].metric), cost);
518 rn = route_node_get (rt, (struct prefix *) &p);
520 /* Lookup current routing table. */
521 if (rn->info)
523 struct ospf_route *cur_or;
525 route_unlock_node (rn);
527 cur_or = rn->info;
529 if (IS_DEBUG_OSPF_EVENT)
530 zlog_debug ("ospf_intra_add_stub(): "
531 "another route to the same prefix found with cost %u",
532 cur_or->cost);
534 /* Compare this distance to the current best cost to the stub
535 network. This is done by looking up the stub network's
536 current routing table entry. If the calculated distance D is
537 larger, go on to examine the next stub network link in the
538 LSA. */
539 if (cost > cur_or->cost)
541 if (IS_DEBUG_OSPF_EVENT)
542 zlog_debug ("ospf_intra_add_stub(): old route is better, exit");
543 return;
546 /* (2) If this step is reached, the stub network's routing table
547 entry must be updated. Calculate the set of next hops that
548 would result from using the stub network link. This
549 calculation is shown in Section 16.1.1; input to this
550 calculation is the destination (the stub network) and the
551 parent vertex (the router vertex). If the distance D is the
552 same as the current routing table cost, simply add this set
553 of next hops to the routing table entry's list of next hops.
554 In this case, the routing table already has a Link State
555 Origin. If this Link State Origin is a router-LSA whose Link
556 State ID is smaller than V's Router ID, reset the Link State
557 Origin to V's router-LSA. */
559 if (cost == cur_or->cost)
561 if (IS_DEBUG_OSPF_EVENT)
562 zlog_debug ("ospf_intra_add_stub(): routes are equal, merge");
564 ospf_route_copy_nexthops_from_vertex (cur_or, v);
566 if (IPV4_ADDR_CMP (&cur_or->u.std.origin->id, &lsa->header.id) < 0)
567 cur_or->u.std.origin = (struct lsa_header *) lsa;
568 return;
571 /* Otherwise D is smaller than the routing table cost.
572 Overwrite the current routing table entry by setting the
573 routing table entry's cost to D, and by setting the entry's
574 list of next hops to the newly calculated set. Set the
575 routing table entry's Link State Origin to V's router-LSA.
576 Then go on to examine the next stub network link. */
578 if (cost < cur_or->cost)
580 if (IS_DEBUG_OSPF_EVENT)
581 zlog_debug ("ospf_intra_add_stub(): new route is better, set it");
583 cur_or->cost = cost;
585 list_delete_all_node (cur_or->paths);
587 ospf_route_copy_nexthops_from_vertex (cur_or, v);
589 cur_or->u.std.origin = (struct lsa_header *) lsa;
590 return;
594 if (IS_DEBUG_OSPF_EVENT)
595 zlog_debug ("ospf_intra_add_stub(): installing new route");
597 or = ospf_route_new ();
599 or->id = v->id;
600 or->u.std.area_id = area->area_id;
601 or->u.std.external_routing = area->external_routing;
602 or->path_type = OSPF_PATH_INTRA_AREA;
603 or->cost = cost;
604 or->type = OSPF_DESTINATION_NETWORK;
605 or->u.std.origin = (struct lsa_header *) lsa;
607 /* Nexthop is depend on connection type. */
608 if (v != area->spf)
610 if (IS_DEBUG_OSPF_EVENT)
611 zlog_debug ("ospf_intra_add_stub(): this network is on remote router");
612 ospf_route_copy_nexthops_from_vertex (or, v);
614 else
616 if (IS_DEBUG_OSPF_EVENT)
617 zlog_debug ("ospf_intra_add_stub(): this network is on this router");
619 if ((oi = ospf_if_lookup_by_prefix (area->ospf, &p)))
621 if (IS_DEBUG_OSPF_EVENT)
622 zlog_debug ("ospf_intra_add_stub(): the interface is %s",
623 IF_NAME (oi));
625 path = ospf_path_new ();
626 path->nexthop.s_addr = 0;
627 path->oi = oi;
628 listnode_add (or->paths, path);
630 else
632 if (IS_DEBUG_OSPF_EVENT)
633 zlog_debug ("ospf_intra_add_stub(): where's the interface ?");
637 rn->info = or;
639 if (IS_DEBUG_OSPF_EVENT)
640 zlog_debug("ospf_intra_add_stub(): Stop");
643 const char *ospf_path_type_str[] =
645 "unknown-type",
646 "intra-area",
647 "inter-area",
648 "type1-external",
649 "type2-external"
652 void
653 ospf_route_table_dump (struct route_table *rt)
655 struct route_node *rn;
656 struct ospf_route *or;
657 char buf1[BUFSIZ];
658 char buf2[BUFSIZ];
659 struct listnode *pnode;
660 struct ospf_path *path;
662 #if 0
663 zlog_debug ("Type Dest Area Path Type Cost Next Adv.");
664 zlog_debug (" Hop(s) Router(s)");
665 #endif /* 0 */
667 zlog_debug ("========== OSPF routing table ==========");
668 for (rn = route_top (rt); rn; rn = route_next (rn))
669 if ((or = rn->info) != NULL)
671 if (or->type == OSPF_DESTINATION_NETWORK)
673 zlog_debug ("N %s/%d\t%s\t%s\t%d",
674 inet_ntop (AF_INET, &rn->p.u.prefix4, buf1, BUFSIZ),
675 rn->p.prefixlen,
676 inet_ntop (AF_INET, &or->u.std.area_id, buf2,
677 BUFSIZ),
678 ospf_path_type_str[or->path_type],
679 or->cost);
680 for (ALL_LIST_ELEMENTS_RO (or->paths, pnode, path))
681 zlog_debug (" -> %s", inet_ntoa (path->nexthop));
683 else
684 zlog_debug ("R %s\t%s\t%s\t%d",
685 inet_ntop (AF_INET, &rn->p.u.prefix4, buf1, BUFSIZ),
686 inet_ntop (AF_INET, &or->u.std.area_id, buf2,
687 BUFSIZ),
688 ospf_path_type_str[or->path_type],
689 or->cost);
691 zlog_debug ("========================================");
694 /* This is 16.4.1 implementation.
695 o Intra-area paths using non-backbone areas are always the most preferred.
696 o The other paths, intra-area backbone paths and inter-area paths,
697 are of equal preference. */
698 static int
699 ospf_asbr_route_cmp (struct ospf *ospf, struct ospf_route *r1,
700 struct ospf_route *r2)
702 u_char r1_type, r2_type;
704 r1_type = r1->path_type;
705 r2_type = r2->path_type;
707 /* If RFC1583Compat flag is on -- all paths are equal. */
708 if (CHECK_FLAG (ospf->config, OSPF_RFC1583_COMPATIBLE))
709 return 0;
711 /* r1/r2 itself is backbone, and it's Inter-area path. */
712 if (OSPF_IS_AREA_ID_BACKBONE (r1->u.std.area_id))
713 r1_type = OSPF_PATH_INTER_AREA;
714 if (OSPF_IS_AREA_ID_BACKBONE (r2->u.std.area_id))
715 r2_type = OSPF_PATH_INTER_AREA;
717 return (r1_type - r2_type);
720 /* Compare two routes.
721 ret < 0 -- r1 is better.
722 ret == 0 -- r1 and r2 are the same.
723 ret > 0 -- r2 is better. */
725 ospf_route_cmp (struct ospf *ospf, struct ospf_route *r1,
726 struct ospf_route *r2)
728 int ret = 0;
730 /* Path types of r1 and r2 are not the same. */
731 if ((ret = (r1->path_type - r2->path_type)))
732 return ret;
734 if (IS_DEBUG_OSPF_EVENT)
735 zlog_debug ("Route[Compare]: Path types are the same.");
736 /* Path types are the same, compare any cost. */
737 switch (r1->path_type)
739 case OSPF_PATH_INTRA_AREA:
740 case OSPF_PATH_INTER_AREA:
741 break;
742 case OSPF_PATH_TYPE1_EXTERNAL:
743 if (!CHECK_FLAG (ospf->config, OSPF_RFC1583_COMPATIBLE))
745 ret = ospf_asbr_route_cmp (ospf, r1->u.ext.asbr, r2->u.ext.asbr);
746 if (ret != 0)
747 return ret;
749 break;
750 case OSPF_PATH_TYPE2_EXTERNAL:
751 if ((ret = (r1->u.ext.type2_cost - r2->u.ext.type2_cost)))
752 return ret;
754 if (!CHECK_FLAG (ospf->config, OSPF_RFC1583_COMPATIBLE))
756 ret = ospf_asbr_route_cmp (ospf, r1->u.ext.asbr, r2->u.ext.asbr);
757 if (ret != 0)
758 return ret;
760 break;
763 /* Anyway, compare the costs. */
764 return (r1->cost - r2->cost);
767 static int
768 ospf_path_exist (struct list *plist, struct in_addr nexthop,
769 struct ospf_interface *oi)
771 struct listnode *node, *nnode;
772 struct ospf_path *path;
774 for (ALL_LIST_ELEMENTS (plist, node, nnode, path))
775 if (IPV4_ADDR_SAME (&path->nexthop, &nexthop) && path->oi == oi)
776 return 1;
778 return 0;
781 void
782 ospf_route_copy_nexthops_from_vertex (struct ospf_route *to,
783 struct vertex *v)
785 struct listnode *node;
786 struct ospf_path *path;
787 struct vertex_nexthop *nexthop;
788 struct vertex_parent *vp;
790 assert (to->paths);
792 for (ALL_LIST_ELEMENTS_RO (v->parents, node, vp))
794 nexthop = vp->nexthop;
796 if (nexthop->oi != NULL)
798 if (! ospf_path_exist (to->paths, nexthop->router, nexthop->oi))
800 path = ospf_path_new ();
801 path->nexthop = nexthop->router;
802 path->oi = nexthop->oi;
803 listnode_add (to->paths, path);
809 struct ospf_path *
810 ospf_path_lookup (struct list *plist, struct ospf_path *path)
812 struct listnode *node;
813 struct ospf_path *op;
815 for (ALL_LIST_ELEMENTS_RO (plist, node, op))
816 if (IPV4_ADDR_SAME (&op->nexthop, &path->nexthop) &&
817 IPV4_ADDR_SAME (&op->adv_router, &path->adv_router))
818 return op;
820 return NULL;
823 void
824 ospf_route_copy_nexthops (struct ospf_route *to, struct list *from)
826 struct listnode *node, *nnode;
827 struct ospf_path *path;
829 assert (to->paths);
831 for (ALL_LIST_ELEMENTS (from, node, nnode, path))
832 /* The same routes are just discarded. */
833 if (!ospf_path_lookup (to->paths, path))
834 listnode_add (to->paths, ospf_path_dup (path));
837 void
838 ospf_route_subst_nexthops (struct ospf_route *to, struct list *from)
841 list_delete_all_node (to->paths);
842 ospf_route_copy_nexthops (to, from);
845 void
846 ospf_route_subst (struct route_node *rn, struct ospf_route *new_or,
847 struct ospf_route *over)
849 route_lock_node (rn);
850 ospf_route_free (rn->info);
852 ospf_route_copy_nexthops (new_or, over->paths);
853 rn->info = new_or;
854 route_unlock_node (rn);
857 void
858 ospf_route_add (struct route_table *rt, struct prefix_ipv4 *p,
859 struct ospf_route *new_or, struct ospf_route *over)
861 struct route_node *rn;
863 rn = route_node_get (rt, (struct prefix *) p);
865 ospf_route_copy_nexthops (new_or, over->paths);
867 if (rn->info)
869 if (IS_DEBUG_OSPF_EVENT)
870 zlog_debug ("ospf_route_add(): something's wrong !");
871 route_unlock_node (rn);
872 return;
875 rn->info = new_or;
878 void
879 ospf_prune_unreachable_networks (struct route_table *rt)
881 struct route_node *rn, *next;
882 struct ospf_route *or;
884 if (IS_DEBUG_OSPF_EVENT)
885 zlog_debug ("Pruning unreachable networks");
887 for (rn = route_top (rt); rn; rn = next)
889 next = route_next (rn);
890 if (rn->info != NULL)
892 or = rn->info;
893 if (listcount (or->paths) == 0)
895 if (IS_DEBUG_OSPF_EVENT)
896 zlog_debug ("Pruning route to %s/%d",
897 inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen);
899 ospf_route_free (or);
900 rn->info = NULL;
901 route_unlock_node (rn);
907 void
908 ospf_prune_unreachable_routers (struct route_table *rtrs)
910 struct route_node *rn, *next;
911 struct ospf_route *or;
912 struct listnode *node, *nnode;
913 struct list *paths;
915 if (IS_DEBUG_OSPF_EVENT)
916 zlog_debug ("Pruning unreachable routers");
918 for (rn = route_top (rtrs); rn; rn = next)
920 next = route_next (rn);
921 if ((paths = rn->info) == NULL)
922 continue;
924 for (ALL_LIST_ELEMENTS (paths, node, nnode, or))
926 if (listcount (or->paths) == 0)
928 if (IS_DEBUG_OSPF_EVENT)
930 zlog_debug ("Pruning route to rtr %s",
931 inet_ntoa (rn->p.u.prefix4));
932 zlog_debug (" via area %s",
933 inet_ntoa (or->u.std.area_id));
936 listnode_delete (paths, or);
937 ospf_route_free (or);
941 if (listcount (paths) == 0)
943 if (IS_DEBUG_OSPF_EVENT)
944 zlog_debug ("Pruning router node %s", inet_ntoa (rn->p.u.prefix4));
946 list_delete (paths);
947 rn->info = NULL;
948 route_unlock_node (rn);
954 ospf_add_discard_route (struct route_table *rt, struct ospf_area *area,
955 struct prefix_ipv4 *p)
957 struct route_node *rn;
958 struct ospf_route *or, *new_or;
960 rn = route_node_get (rt, (struct prefix *) p);
962 if (rn == NULL)
964 if (IS_DEBUG_OSPF_EVENT)
965 zlog_debug ("ospf_add_discard_route(): router installation error");
966 return 0;
969 if (rn->info) /* If the route to the same destination is found */
971 route_unlock_node (rn);
973 or = rn->info;
975 if (or->path_type == OSPF_PATH_INTRA_AREA)
977 if (IS_DEBUG_OSPF_EVENT)
978 zlog_debug ("ospf_add_discard_route(): "
979 "an intra-area route exists");
980 return 0;
983 if (or->type == OSPF_DESTINATION_DISCARD)
985 if (IS_DEBUG_OSPF_EVENT)
986 zlog_debug ("ospf_add_discard_route(): "
987 "discard entry already installed");
988 return 0;
991 ospf_route_free (rn->info);
994 new_or = ospf_route_new ();
995 new_or->type = OSPF_DESTINATION_DISCARD;
996 new_or->id.s_addr = 0;
997 new_or->cost = 0;
998 new_or->u.std.area_id = area->area_id;
999 new_or->u.std.external_routing = area->external_routing;
1000 new_or->path_type = OSPF_PATH_INTER_AREA;
1001 rn->info = new_or;
1003 ospf_zebra_add_discard (p);
1005 return 1;
1008 void
1009 ospf_delete_discard_route (struct prefix_ipv4 *p)
1011 ospf_zebra_delete_discard(p);