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
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
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"
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
;
59 ospf_route_free (struct ospf_route
*or)
62 list_delete (or->paths
);
64 XFREE (MTYPE_OSPF_ROUTE
, or);
70 struct ospf_path
*new;
72 new = XCALLOC (MTYPE_OSPF_PATH
, sizeof (struct ospf_path
));
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
));
89 ospf_path_free (struct ospf_path
*op
)
91 XFREE (MTYPE_OSPF_PATH
, op
);
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
,
106 else if (or->type
== OSPF_DESTINATION_DISCARD
)
107 ospf_zebra_delete_discard ((struct prefix_ipv4
*) &rn
->p
);
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);
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
;
142 if (! rt
|| ! prefix
)
145 rn
= route_node_lookup (rt
, (struct prefix
*) prefix
);
146 if (! rn
|| ! rn
->info
)
149 route_unlock_node (rn
);
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
)
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
))
168 if (op
->ifindex
!= newop
->ifindex
)
173 else if (prefix_same (&rn
->p
, (struct prefix
*) prefix
))
179 /* delete routes generated from AS-External routes if there is a inter/intra
183 ospf_route_delete_same_ext(struct route_table
*external_routes
,
184 struct route_table
*routes
)
186 struct route_node
*rn
,
189 if ( (external_routes
== NULL
) || (routes
== NULL
) )
192 /* Remove deleted routes */
193 for ( rn
= route_top (routes
); rn
; rn
= route_next (rn
) )
197 struct prefix_ipv4
*p
= (struct prefix_ipv4
*)(&rn
->p
);
198 if ( (ext_rn
= route_node_lookup (external_routes
, (struct prefix
*)p
)) )
202 ospf_zebra_delete (p
, ext_rn
->info
);
203 ospf_route_free( ext_rn
->info
);
206 route_unlock_node (ext_rn
);
212 /* rt: Old, cmprt: New */
214 ospf_route_delete_uniq (struct route_table
*rt
, struct route_table
*cmprt
)
216 struct route_node
*rn
;
217 struct ospf_route
*or;
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
)
224 if (or->type
== OSPF_DESTINATION_NETWORK
)
226 if (! ospf_route_match_same (cmprt
,
227 (struct prefix_ipv4
*) &rn
->p
, or))
228 ospf_zebra_delete ((struct prefix_ipv4
*) &rn
->p
, or);
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
);
237 /* Install routes to table. */
239 ospf_route_install (struct ospf
*ospf
, struct route_table
*rt
)
241 struct route_node
*rn
;
242 struct ospf_route
*or;
244 /* rt contains new routing table, new_table contains an old one.
247 ospf_route_table_free (ospf
->old_table
);
249 ospf
->old_table
= ospf
->new_table
;
250 ospf
->new_table
= rt
;
252 /* Delete old routes. */
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
);
258 /* Install new routes. */
259 for (rn
= route_top (rt
); rn
; rn
= route_next (rn
))
260 if ((or = rn
->info
) != NULL
)
262 if (or->type
== OSPF_DESTINATION_NETWORK
)
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);
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
);
276 ospf_intra_route_add (struct route_table
*rt
, struct vertex
*v
,
277 struct ospf_area
*area
)
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
;
288 if (v
->type
== OSPF_VERTEX_ROUTER
)
289 p
.prefixlen
= IPV4_MAX_BITLEN
;
292 struct network_lsa
*lsa
= (struct network_lsa
*) v
->lsa
;
293 p
.prefixlen
= ip_masklen (lsa
->mask
);
295 apply_mask_ipv4 (&p
);
297 rn
= route_node_get (rt
, (struct prefix
*) &p
);
300 zlog_warn ("Same routing information exists for %s", inet_ntoa (v
->id
));
301 route_unlock_node (rn
);
305 or = ospf_route_new ();
307 if (v
->type
== OSPF_VERTEX_NETWORK
)
309 or->type
= OSPF_DESTINATION_NETWORK
;
311 for (ALL_LIST_ELEMENTS (v
->parents
, node
, nnode
, parent
))
313 path
= ospf_path_new ();
314 path
->nexthop
= parent
->nexthop
->router
;
315 listnode_add (or->paths
, path
);
319 or->type
= OSPF_DESTINATION_ROUTER
;
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
;
330 /* RFC2328 16.1. (4). For "router". */
332 ospf_intra_add_router (struct route_table
*rt
, struct vertex
*v
,
333 struct ospf_area
*area
)
335 struct route_node
*rn
;
336 struct ospf_route
*or;
337 struct prefix_ipv4 p
;
338 struct router_lsa
*lsa
;
340 if (IS_DEBUG_OSPF_EVENT
)
341 zlog_debug ("ospf_intra_add_router: Start");
343 lsa
= (struct router_lsa
*) v
->lsa
;
345 if (IS_DEBUG_OSPF_EVENT
)
346 zlog_debug ("ospf_intra_add_router: LS ID: %s",
347 inet_ntoa (lsa
->header
.id
));
349 if (!OSPF_IS_AREA_BACKBONE(area
))
350 ospf_vl_up_check (area
, lsa
->header
.id
, v
);
352 if (!CHECK_FLAG (lsa
->flags
, ROUTER_LSA_SHORTCUT
))
353 area
->shortcut_capability
= 0;
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
358 if (! IS_ROUTER_LSA_BORDER (lsa
) && ! IS_ROUTER_LSA_EXTERNAL (lsa
))
360 if (IS_DEBUG_OSPF_EVENT
)
361 zlog_debug ("ospf_intra_add_router: "
362 "this router is neither ASBR nor ABR, skipping it");
366 /* Update ABR and ASBR count in this area. */
367 if (IS_ROUTER_LSA_BORDER (lsa
))
369 if (IS_ROUTER_LSA_EXTERNAL (lsa
))
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 ();
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
;
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). */
400 p
.prefixlen
= IPV4_MAX_BITLEN
;
402 if (IS_DEBUG_OSPF_EVENT
)
403 zlog_debug ("ospf_intra_add_router: talking about %s/%d",
404 inet_ntoa (p
.prefix
), p
.prefixlen
);
406 rn
= route_node_get (rt
, (struct prefix
*) &p
);
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 ();
412 route_unlock_node (rn
);
414 ospf_route_copy_nexthops_from_vertex (or, v
);
416 listnode_add (rn
->info
, or);
418 if (IS_DEBUG_OSPF_EVENT
)
419 zlog_debug ("ospf_intra_add_router: Stop");
422 /* RFC2328 16.1. (4). For transit network. */
424 ospf_intra_add_transit (struct route_table
*rt
, struct vertex
*v
,
425 struct ospf_area
*area
)
427 struct route_node
*rn
;
428 struct ospf_route
*or;
429 struct prefix_ipv4 p
;
430 struct network_lsa
*lsa
;
432 lsa
= (struct network_lsa
*) v
->lsa
;
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). */
441 p
.prefixlen
= ip_masklen (lsa
->mask
);
442 apply_mask_ipv4 (&p
);
444 rn
= route_node_get (rt
, (struct prefix
*) &p
);
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. */
456 struct ospf_route
*cur_or
;
458 route_unlock_node (rn
);
461 if (v
->distance
> cur_or
->cost
||
462 IPV4_ADDR_CMP (&cur_or
->u
.std
.origin
->id
, &lsa
->header
.id
) > 0)
465 ospf_route_free (rn
->info
);
468 or = ospf_route_new ();
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
;
478 ospf_route_copy_nexthops_from_vertex (or, v
);
483 /* RFC2328 16.1. second stage. */
485 ospf_intra_add_stub (struct route_table
*rt
, struct router_lsa_link
*link
,
486 struct vertex
*v
, struct ospf_area
*area
,
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
;
497 if (IS_DEBUG_OSPF_EVENT
)
498 zlog_debug ("ospf_intra_add_stub(): Start");
500 lsa
= (struct router_lsa
*) v
->lsa
;
503 p
.prefix
= link
->link_id
;
504 p
.prefixlen
= ip_masklen (link
->link_data
);
505 apply_mask_ipv4 (&p
);
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
);
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
515 cost
= v
->distance
+ ntohs (link
->m
[0].metric
);
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
);
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.
525 if (parent_is_root
&& link
->link_data
.s_addr
== 0xffffffff &&
526 ospf_if_lookup_by_local_addr (area
->ospf
, NULL
, link
->link_id
))
528 if (IS_DEBUG_OSPF_EVENT
)
529 zlog_debug ("%s: ignoring host route %s/32 to self.",
530 __func__
, inet_ntoa (link
->link_id
));
534 rn
= route_node_get (rt
, (struct prefix
*) &p
);
536 /* Lookup current routing table. */
539 struct ospf_route
*cur_or
;
541 route_unlock_node (rn
);
545 if (IS_DEBUG_OSPF_EVENT
)
546 zlog_debug ("ospf_intra_add_stub(): "
547 "another route to the same prefix found with cost %u",
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
555 if (cost
> cur_or
->cost
)
557 if (IS_DEBUG_OSPF_EVENT
)
558 zlog_debug ("ospf_intra_add_stub(): old route is better, exit");
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. */
575 if (cost
== cur_or
->cost
)
577 if (IS_DEBUG_OSPF_EVENT
)
578 zlog_debug ("ospf_intra_add_stub(): routes are equal, merge");
580 ospf_route_copy_nexthops_from_vertex (cur_or
, v
);
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
;
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. */
594 if (cost
< cur_or
->cost
)
596 if (IS_DEBUG_OSPF_EVENT
)
597 zlog_debug ("ospf_intra_add_stub(): new route is better, set it");
601 list_delete_all_node (cur_or
->paths
);
603 ospf_route_copy_nexthops_from_vertex (cur_or
, v
);
605 cur_or
->u
.std
.origin
= (struct lsa_header
*) lsa
;
610 if (IS_DEBUG_OSPF_EVENT
)
611 zlog_debug ("ospf_intra_add_stub(): installing new route");
613 or = ospf_route_new ();
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
;
620 or->type
= OSPF_DESTINATION_NETWORK
;
621 or->u
.std
.origin
= (struct lsa_header
*) lsa
;
623 /* Nexthop is depend on connection type. */
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
);
632 if (IS_DEBUG_OSPF_EVENT
)
633 zlog_debug ("ospf_intra_add_stub(): this network is on this router");
635 if ((oi
= ospf_if_lookup_by_prefix (area
->ospf
, &p
)))
637 if (IS_DEBUG_OSPF_EVENT
)
638 zlog_debug ("ospf_intra_add_stub(): the interface is %s",
641 path
= ospf_path_new ();
642 path
->nexthop
.s_addr
= 0;
643 path
->ifindex
= oi
->ifp
->ifindex
;
644 listnode_add (or->paths
, path
);
648 if (IS_DEBUG_OSPF_EVENT
)
649 zlog_debug ("ospf_intra_add_stub(): where's the interface ?");
655 if (IS_DEBUG_OSPF_EVENT
)
656 zlog_debug("ospf_intra_add_stub(): Stop");
659 const char *ospf_path_type_str
[] =
669 ospf_route_table_dump (struct route_table
*rt
)
671 struct route_node
*rn
;
672 struct ospf_route
*or;
675 struct listnode
*pnode
;
676 struct ospf_path
*path
;
679 zlog_debug ("Type Dest Area Path Type Cost Next Adv.");
680 zlog_debug (" Hop(s) Router(s)");
683 zlog_debug ("========== OSPF routing table ==========");
684 for (rn
= route_top (rt
); rn
; rn
= route_next (rn
))
685 if ((or = rn
->info
) != NULL
)
687 if (or->type
== OSPF_DESTINATION_NETWORK
)
689 zlog_debug ("N %s/%d\t%s\t%s\t%d",
690 inet_ntop (AF_INET
, &rn
->p
.u
.prefix4
, buf1
, BUFSIZ
),
692 inet_ntop (AF_INET
, &or->u
.std
.area_id
, buf2
,
694 ospf_path_type_str
[or->path_type
],
696 for (ALL_LIST_ELEMENTS_RO (or->paths
, pnode
, path
))
697 zlog_debug (" -> %s", inet_ntoa (path
->nexthop
));
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
,
704 ospf_path_type_str
[or->path_type
],
707 zlog_debug ("========================================");
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. */
715 ospf_asbr_route_cmp (struct ospf
*ospf
, struct ospf_route
*r1
,
716 struct ospf_route
*r2
)
718 u_char r1_type
, r2_type
;
720 r1_type
= r1
->path_type
;
721 r2_type
= r2
->path_type
;
723 /* If RFC1583Compat flag is on -- all paths are equal. */
724 if (CHECK_FLAG (ospf
->config
, OSPF_RFC1583_COMPATIBLE
))
727 /* r1/r2 itself is backbone, and it's Inter-area path. */
728 if (OSPF_IS_AREA_ID_BACKBONE (r1
->u
.std
.area_id
))
729 r1_type
= OSPF_PATH_INTER_AREA
;
730 if (OSPF_IS_AREA_ID_BACKBONE (r2
->u
.std
.area_id
))
731 r2_type
= OSPF_PATH_INTER_AREA
;
733 return (r1_type
- r2_type
);
736 /* Compare two routes.
737 ret < 0 -- r1 is better.
738 ret == 0 -- r1 and r2 are the same.
739 ret > 0 -- r2 is better. */
741 ospf_route_cmp (struct ospf
*ospf
, struct ospf_route
*r1
,
742 struct ospf_route
*r2
)
746 /* Path types of r1 and r2 are not the same. */
747 if ((ret
= (r1
->path_type
- r2
->path_type
)))
750 if (IS_DEBUG_OSPF_EVENT
)
751 zlog_debug ("Route[Compare]: Path types are the same.");
752 /* Path types are the same, compare any cost. */
753 switch (r1
->path_type
)
755 case OSPF_PATH_INTRA_AREA
:
756 case OSPF_PATH_INTER_AREA
:
758 case OSPF_PATH_TYPE1_EXTERNAL
:
759 if (!CHECK_FLAG (ospf
->config
, OSPF_RFC1583_COMPATIBLE
))
761 ret
= ospf_asbr_route_cmp (ospf
, r1
->u
.ext
.asbr
, r2
->u
.ext
.asbr
);
766 case OSPF_PATH_TYPE2_EXTERNAL
:
767 if ((ret
= (r1
->u
.ext
.type2_cost
- r2
->u
.ext
.type2_cost
)))
770 if (!CHECK_FLAG (ospf
->config
, OSPF_RFC1583_COMPATIBLE
))
772 ret
= ospf_asbr_route_cmp (ospf
, r1
->u
.ext
.asbr
, r2
->u
.ext
.asbr
);
779 /* Anyway, compare the costs. */
780 return (r1
->cost
- r2
->cost
);
784 ospf_path_exist (struct list
*plist
, struct in_addr nexthop
,
785 struct ospf_interface
*oi
)
787 struct listnode
*node
, *nnode
;
788 struct ospf_path
*path
;
790 for (ALL_LIST_ELEMENTS (plist
, node
, nnode
, path
))
791 if (IPV4_ADDR_SAME (&path
->nexthop
, &nexthop
) &&
792 path
->ifindex
== oi
->ifp
->ifindex
)
799 ospf_route_copy_nexthops_from_vertex (struct ospf_route
*to
,
802 struct listnode
*node
;
803 struct ospf_path
*path
;
804 struct vertex_nexthop
*nexthop
;
805 struct vertex_parent
*vp
;
809 for (ALL_LIST_ELEMENTS_RO (v
->parents
, node
, vp
))
811 nexthop
= vp
->nexthop
;
813 if (nexthop
->oi
!= NULL
)
815 if (! ospf_path_exist (to
->paths
, nexthop
->router
, nexthop
->oi
))
817 path
= ospf_path_new ();
818 path
->nexthop
= nexthop
->router
;
819 path
->ifindex
= nexthop
->oi
->ifp
->ifindex
;
820 listnode_add (to
->paths
, path
);
827 ospf_path_lookup (struct list
*plist
, struct ospf_path
*path
)
829 struct listnode
*node
;
830 struct ospf_path
*op
;
832 for (ALL_LIST_ELEMENTS_RO (plist
, node
, op
))
834 if (!IPV4_ADDR_SAME (&op
->nexthop
, &path
->nexthop
))
836 if (!IPV4_ADDR_SAME (&op
->adv_router
, &path
->adv_router
))
838 if (op
->ifindex
!= path
->ifindex
)
846 ospf_route_copy_nexthops (struct ospf_route
*to
, struct list
*from
)
848 struct listnode
*node
, *nnode
;
849 struct ospf_path
*path
;
853 for (ALL_LIST_ELEMENTS (from
, node
, nnode
, path
))
854 /* The same routes are just discarded. */
855 if (!ospf_path_lookup (to
->paths
, path
))
856 listnode_add (to
->paths
, ospf_path_dup (path
));
860 ospf_route_subst_nexthops (struct ospf_route
*to
, struct list
*from
)
863 list_delete_all_node (to
->paths
);
864 ospf_route_copy_nexthops (to
, from
);
868 ospf_route_subst (struct route_node
*rn
, struct ospf_route
*new_or
,
869 struct ospf_route
*over
)
871 route_lock_node (rn
);
872 ospf_route_free (rn
->info
);
874 ospf_route_copy_nexthops (new_or
, over
->paths
);
876 route_unlock_node (rn
);
880 ospf_route_add (struct route_table
*rt
, struct prefix_ipv4
*p
,
881 struct ospf_route
*new_or
, struct ospf_route
*over
)
883 struct route_node
*rn
;
885 rn
= route_node_get (rt
, (struct prefix
*) p
);
887 ospf_route_copy_nexthops (new_or
, over
->paths
);
891 if (IS_DEBUG_OSPF_EVENT
)
892 zlog_debug ("ospf_route_add(): something's wrong !");
893 route_unlock_node (rn
);
901 ospf_prune_unreachable_networks (struct route_table
*rt
)
903 struct route_node
*rn
, *next
;
904 struct ospf_route
*or;
906 if (IS_DEBUG_OSPF_EVENT
)
907 zlog_debug ("Pruning unreachable networks");
909 for (rn
= route_top (rt
); rn
; rn
= next
)
911 next
= route_next (rn
);
912 if (rn
->info
!= NULL
)
915 if (listcount (or->paths
) == 0)
917 if (IS_DEBUG_OSPF_EVENT
)
918 zlog_debug ("Pruning route to %s/%d",
919 inet_ntoa (rn
->p
.u
.prefix4
), rn
->p
.prefixlen
);
921 ospf_route_free (or);
923 route_unlock_node (rn
);
930 ospf_prune_unreachable_routers (struct route_table
*rtrs
)
932 struct route_node
*rn
, *next
;
933 struct ospf_route
*or;
934 struct listnode
*node
, *nnode
;
937 if (IS_DEBUG_OSPF_EVENT
)
938 zlog_debug ("Pruning unreachable routers");
940 for (rn
= route_top (rtrs
); rn
; rn
= next
)
942 next
= route_next (rn
);
943 if ((paths
= rn
->info
) == NULL
)
946 for (ALL_LIST_ELEMENTS (paths
, node
, nnode
, or))
948 if (listcount (or->paths
) == 0)
950 if (IS_DEBUG_OSPF_EVENT
)
952 zlog_debug ("Pruning route to rtr %s",
953 inet_ntoa (rn
->p
.u
.prefix4
));
954 zlog_debug (" via area %s",
955 inet_ntoa (or->u
.std
.area_id
));
958 listnode_delete (paths
, or);
959 ospf_route_free (or);
963 if (listcount (paths
) == 0)
965 if (IS_DEBUG_OSPF_EVENT
)
966 zlog_debug ("Pruning router node %s", inet_ntoa (rn
->p
.u
.prefix4
));
970 route_unlock_node (rn
);
976 ospf_add_discard_route (struct route_table
*rt
, struct ospf_area
*area
,
977 struct prefix_ipv4
*p
)
979 struct route_node
*rn
;
980 struct ospf_route
*or, *new_or
;
982 rn
= route_node_get (rt
, (struct prefix
*) p
);
986 if (IS_DEBUG_OSPF_EVENT
)
987 zlog_debug ("ospf_add_discard_route(): router installation error");
991 if (rn
->info
) /* If the route to the same destination is found */
993 route_unlock_node (rn
);
997 if (or->path_type
== OSPF_PATH_INTRA_AREA
)
999 if (IS_DEBUG_OSPF_EVENT
)
1000 zlog_debug ("ospf_add_discard_route(): "
1001 "an intra-area route exists");
1005 if (or->type
== OSPF_DESTINATION_DISCARD
)
1007 if (IS_DEBUG_OSPF_EVENT
)
1008 zlog_debug ("ospf_add_discard_route(): "
1009 "discard entry already installed");
1013 ospf_route_free (rn
->info
);
1016 new_or
= ospf_route_new ();
1017 new_or
->type
= OSPF_DESTINATION_DISCARD
;
1018 new_or
->id
.s_addr
= 0;
1020 new_or
->u
.std
.area_id
= area
->area_id
;
1021 new_or
->u
.std
.external_routing
= area
->external_routing
;
1022 new_or
->path_type
= OSPF_PATH_INTER_AREA
;
1025 ospf_zebra_add_discard (p
);
1031 ospf_delete_discard_route (struct prefix_ipv4
*p
)
1033 ospf_zebra_delete_discard(p
);