]>
git.proxmox.com Git - mirror_frr.git/blob - ospfd/ospf_route.c
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 along
18 * with this program; see the file COPYING; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
31 #include "sockunion.h"
33 #include "ospfd/ospfd.h"
34 #include "ospfd/ospf_interface.h"
35 #include "ospfd/ospf_asbr.h"
36 #include "ospfd/ospf_lsa.h"
37 #include "ospfd/ospf_route.h"
38 #include "ospfd/ospf_spf.h"
39 #include "ospfd/ospf_zebra.h"
40 #include "ospfd/ospf_dump.h"
42 struct ospf_route
*ospf_route_new()
44 struct ospf_route
*new;
46 new = XCALLOC(MTYPE_OSPF_ROUTE
, sizeof(struct ospf_route
));
48 new->paths
= list_new();
49 new->paths
->del
= (void (*)(void *))ospf_path_free
;
54 void ospf_route_free(struct ospf_route
* or)
57 list_delete(or->paths
);
59 XFREE(MTYPE_OSPF_ROUTE
, or);
62 struct ospf_path
*ospf_path_new()
64 struct ospf_path
*new;
66 new = XCALLOC(MTYPE_OSPF_PATH
, sizeof(struct ospf_path
));
71 static struct ospf_path
*ospf_path_dup(struct ospf_path
*path
)
73 struct ospf_path
*new;
75 new = ospf_path_new();
76 memcpy(new, path
, sizeof(struct ospf_path
));
81 void ospf_path_free(struct ospf_path
*op
)
83 XFREE(MTYPE_OSPF_PATH
, op
);
86 void ospf_route_delete(struct route_table
*rt
)
88 struct route_node
*rn
;
89 struct ospf_route
* or ;
91 for (rn
= route_top(rt
); rn
; rn
= route_next(rn
))
92 if ((or = rn
->info
) != NULL
) {
93 if (or->type
== OSPF_DESTINATION_NETWORK
)
94 ospf_zebra_delete((struct prefix_ipv4
*)&rn
->p
,
96 else if (or->type
== OSPF_DESTINATION_DISCARD
)
97 ospf_zebra_delete_discard(
98 (struct prefix_ipv4
*)&rn
->p
);
102 void ospf_route_table_free(struct route_table
*rt
)
104 struct route_node
*rn
;
105 struct ospf_route
* or ;
107 for (rn
= route_top(rt
); rn
; rn
= route_next(rn
))
108 if ((or = rn
->info
) != NULL
) {
112 route_unlock_node(rn
);
115 route_table_finish(rt
);
118 /* If a prefix exists in the new routing table, then return 1,
119 otherwise return 0. Since the ZEBRA-RIB does an implicit
120 withdraw, it is not necessary to send a delete, an add later
121 will act like an implicit delete. */
122 static int ospf_route_exist_new_table(struct route_table
*rt
,
123 struct prefix_ipv4
*prefix
)
125 struct route_node
*rn
;
130 rn
= route_node_lookup(rt
, (struct prefix
*)prefix
);
134 route_unlock_node(rn
);
143 /* If a prefix and a nexthop match any route in the routing table,
144 then return 1, otherwise return 0. */
145 int ospf_route_match_same(struct route_table
*rt
, struct prefix_ipv4
*prefix
,
146 struct ospf_route
*newor
)
148 struct route_node
*rn
;
149 struct ospf_route
* or ;
150 struct ospf_path
*op
;
151 struct ospf_path
*newop
;
158 rn
= route_node_lookup(rt
, (struct prefix
*)prefix
);
159 if (!rn
|| !rn
->info
)
162 route_unlock_node(rn
);
165 if (or->type
== newor
->type
&& or->cost
== newor
->cost
) {
166 if (or->type
== OSPF_DESTINATION_NETWORK
) {
167 if (or->paths
->count
!= newor
->paths
->count
)
170 /* Check each path. */
171 for (n1
= listhead(or->paths
),
172 n2
= listhead(newor
->paths
);
174 n1
= listnextnode(n1
), n2
= listnextnode(n2
)) {
175 op
= listgetdata(n1
);
176 newop
= listgetdata(n2
);
178 if (!IPV4_ADDR_SAME(&op
->nexthop
,
181 if (op
->ifindex
!= newop
->ifindex
)
185 } else if (prefix_same(&rn
->p
, (struct prefix
*)prefix
))
191 /* delete routes generated from AS-External routes if there is a inter/intra
194 static void ospf_route_delete_same_ext(struct route_table
*external_routes
,
195 struct route_table
*routes
)
197 struct route_node
*rn
, *ext_rn
;
199 if ((external_routes
== NULL
) || (routes
== NULL
))
202 /* Remove deleted routes */
203 for (rn
= route_top(routes
); rn
; rn
= route_next(rn
)) {
204 if (rn
&& rn
->info
) {
205 struct prefix_ipv4
*p
= (struct prefix_ipv4
*)(&rn
->p
);
206 if ((ext_rn
= route_node_lookup(external_routes
,
207 (struct prefix
*)p
))) {
209 ospf_zebra_delete(p
, ext_rn
->info
);
210 ospf_route_free(ext_rn
->info
);
213 route_unlock_node(ext_rn
);
219 /* rt: Old, cmprt: New */
220 static void ospf_route_delete_uniq(struct route_table
*rt
,
221 struct route_table
*cmprt
)
223 struct route_node
*rn
;
224 struct ospf_route
* or ;
226 for (rn
= route_top(rt
); rn
; rn
= route_next(rn
))
227 if ((or = rn
->info
) != NULL
)
228 if (or->path_type
== OSPF_PATH_INTRA_AREA
||
229 or->path_type
== OSPF_PATH_INTER_AREA
) {
230 if (or->type
== OSPF_DESTINATION_NETWORK
) {
231 if (!ospf_route_exist_new_table(
233 (struct prefix_ipv4
*)&rn
239 } else if (or->type
== OSPF_DESTINATION_DISCARD
)
240 if (!ospf_route_exist_new_table(
242 (struct prefix_ipv4
*)&rn
244 ospf_zebra_delete_discard(
250 /* Install routes to table. */
251 void ospf_route_install(struct ospf
*ospf
, struct route_table
*rt
)
253 struct route_node
*rn
;
254 struct ospf_route
* or ;
256 /* rt contains new routing table, new_table contains an old one.
259 ospf_route_table_free(ospf
->old_table
);
261 ospf
->old_table
= ospf
->new_table
;
262 ospf
->new_table
= rt
;
264 /* Delete old routes. */
266 ospf_route_delete_uniq(ospf
->old_table
, rt
);
267 if (ospf
->old_external_route
)
268 ospf_route_delete_same_ext(ospf
->old_external_route
, rt
);
270 /* Install new routes. */
271 for (rn
= route_top(rt
); rn
; rn
= route_next(rn
))
272 if ((or = rn
->info
) != NULL
) {
273 if (or->type
== OSPF_DESTINATION_NETWORK
) {
274 if (!ospf_route_match_same(
276 (struct prefix_ipv4
*)&rn
->p
, or))
278 (struct prefix_ipv4
*)&rn
->p
,
280 } else if (or->type
== OSPF_DESTINATION_DISCARD
)
281 if (!ospf_route_match_same(
283 (struct prefix_ipv4
*)&rn
->p
, or))
284 ospf_zebra_add_discard(
285 (struct prefix_ipv4
*)&rn
->p
);
289 /* RFC2328 16.1. (4). For "router". */
290 void ospf_intra_add_router(struct route_table
*rt
, struct vertex
*v
,
291 struct ospf_area
*area
)
293 struct route_node
*rn
;
294 struct ospf_route
* or ;
295 struct prefix_ipv4 p
;
296 struct router_lsa
*lsa
;
298 if (IS_DEBUG_OSPF_EVENT
)
299 zlog_debug("ospf_intra_add_router: Start");
301 lsa
= (struct router_lsa
*)v
->lsa
;
303 if (IS_DEBUG_OSPF_EVENT
)
304 zlog_debug("ospf_intra_add_router: LS ID: %s",
305 inet_ntoa(lsa
->header
.id
));
307 if (!OSPF_IS_AREA_BACKBONE(area
))
308 ospf_vl_up_check(area
, lsa
->header
.id
, v
);
310 if (!CHECK_FLAG(lsa
->flags
, ROUTER_LSA_SHORTCUT
))
311 area
->shortcut_capability
= 0;
313 /* If the newly added vertex is an area border router or AS boundary
314 router, a routing table entry is added whose destination type is
316 if (!IS_ROUTER_LSA_BORDER(lsa
) && !IS_ROUTER_LSA_EXTERNAL(lsa
)) {
317 if (IS_DEBUG_OSPF_EVENT
)
319 "ospf_intra_add_router: "
320 "this router is neither ASBR nor ABR, skipping it");
324 /* Update ABR and ASBR count in this area. */
325 if (IS_ROUTER_LSA_BORDER(lsa
))
327 if (IS_ROUTER_LSA_EXTERNAL(lsa
))
330 /* The Options field found in the associated router-LSA is copied
331 into the routing table entry's Optional capabilities field. Call
332 the newly added vertex Router X. */
333 or = ospf_route_new();
336 or->u
.std
.area_id
= area
->area_id
;
337 or->u
.std
.external_routing
= area
->external_routing
;
338 or->path_type
= OSPF_PATH_INTRA_AREA
;
339 or->cost
= v
->distance
;
340 or->type
= OSPF_DESTINATION_ROUTER
;
341 or->u
.std
.origin
= (struct lsa_header
*)lsa
;
342 or->u
.std
.options
= lsa
->header
.options
;
343 or->u
.std
.flags
= lsa
->flags
;
345 /* If Router X is the endpoint of one of the calculating router's
346 virtual links, and the virtual link uses Area A as Transit area:
347 the virtual link is declared up, the IP address of the virtual
348 interface is set to the IP address of the outgoing interface
349 calculated above for Router X, and the virtual neighbor's IP
350 address is set to Router X's interface address (contained in
351 Router X's router-LSA) that points back to the root of the
352 shortest- path tree; equivalently, this is the interface that
353 points back to Router X's parent vertex on the shortest-path tree
354 (similar to the calculation in Section 16.1.1). */
358 p
.prefixlen
= IPV4_MAX_BITLEN
;
360 if (IS_DEBUG_OSPF_EVENT
)
361 zlog_debug("ospf_intra_add_router: talking about %s/%d",
362 inet_ntoa(p
.prefix
), p
.prefixlen
);
364 rn
= route_node_get(rt
, (struct prefix
*)&p
);
366 /* Note that we keep all routes to ABRs and ASBRs, not only the best */
367 if (rn
->info
== NULL
)
368 rn
->info
= list_new();
370 route_unlock_node(rn
);
372 ospf_route_copy_nexthops_from_vertex(or, v
);
374 listnode_add(rn
->info
, or);
376 if (IS_DEBUG_OSPF_EVENT
)
377 zlog_debug("ospf_intra_add_router: Stop");
380 /* RFC2328 16.1. (4). For transit network. */
381 void ospf_intra_add_transit(struct route_table
*rt
, struct vertex
*v
,
382 struct ospf_area
*area
)
384 struct route_node
*rn
;
385 struct ospf_route
* or ;
386 struct prefix_ipv4 p
;
387 struct network_lsa
*lsa
;
389 lsa
= (struct network_lsa
*)v
->lsa
;
391 /* If the newly added vertex is a transit network, the routing table
392 entry for the network is located. The entry's Destination ID is
393 the IP network number, which can be obtained by masking the
394 Vertex ID (Link State ID) with its associated subnet mask (found
395 in the body of the associated network-LSA). */
398 p
.prefixlen
= ip_masklen(lsa
->mask
);
401 rn
= route_node_get(rt
, (struct prefix
*)&p
);
403 /* If the routing table entry already exists (i.e., there is already
404 an intra-area route to the destination installed in the routing
405 table), multiple vertices have mapped to the same IP network.
406 For example, this can occur when a new Designated Router is being
407 established. In this case, the current routing table entry
408 should be overwritten if and only if the newly found path is just
409 as short and the current routing table entry's Link State Origin
410 has a smaller Link State ID than the newly added vertex' LSA. */
412 struct ospf_route
*cur_or
;
414 route_unlock_node(rn
);
417 if (v
->distance
> cur_or
->cost
418 || IPV4_ADDR_CMP(&cur_or
->u
.std
.origin
->id
, &lsa
->header
.id
)
422 ospf_route_free(rn
->info
);
425 or = ospf_route_new();
428 or->u
.std
.area_id
= area
->area_id
;
429 or->u
.std
.external_routing
= area
->external_routing
;
430 or->path_type
= OSPF_PATH_INTRA_AREA
;
431 or->cost
= v
->distance
;
432 or->type
= OSPF_DESTINATION_NETWORK
;
433 or->u
.std
.origin
= (struct lsa_header
*)lsa
;
435 ospf_route_copy_nexthops_from_vertex(or, v
);
440 /* RFC2328 16.1. second stage. */
441 void ospf_intra_add_stub(struct route_table
*rt
, struct router_lsa_link
*link
,
442 struct vertex
*v
, struct ospf_area
*area
,
443 int parent_is_root
, int lsa_pos
)
446 struct route_node
*rn
;
447 struct ospf_route
* or ;
448 struct prefix_ipv4 p
;
449 struct router_lsa
*lsa
;
450 struct ospf_interface
*oi
;
451 struct ospf_path
*path
;
453 if (IS_DEBUG_OSPF_EVENT
)
454 zlog_debug("ospf_intra_add_stub(): Start");
456 lsa
= (struct router_lsa
*)v
->lsa
;
459 p
.prefix
= link
->link_id
;
460 p
.prefixlen
= ip_masklen(link
->link_data
);
463 if (IS_DEBUG_OSPF_EVENT
)
464 zlog_debug("ospf_intra_add_stub(): processing route to %s/%d",
465 inet_ntoa(p
.prefix
), p
.prefixlen
);
467 /* (1) Calculate the distance D of stub network from the root. D is
468 equal to the distance from the root to the router vertex
469 (calculated in stage 1), plus the stub network link's advertised
471 cost
= v
->distance
+ ntohs(link
->m
[0].metric
);
473 if (IS_DEBUG_OSPF_EVENT
)
475 "ospf_intra_add_stub(): calculated cost is %d + %d = %d",
476 v
->distance
, ntohs(link
->m
[0].metric
), cost
);
478 /* PtP links with /32 masks adds host routes to remote, directly
479 * connected hosts, see RFC 2328, 12.4.1.1, Option 1.
480 * Such routes can just be ignored for the sake of tidyness.
482 if (parent_is_root
&& link
->link_data
.s_addr
== 0xffffffff
483 && ospf_if_lookup_by_local_addr(area
->ospf
, NULL
, link
->link_id
)) {
484 if (IS_DEBUG_OSPF_EVENT
)
485 zlog_debug("%s: ignoring host route %s/32 to self.",
486 __func__
, inet_ntoa(link
->link_id
));
490 rn
= route_node_get(rt
, (struct prefix
*)&p
);
492 /* Lookup current routing table. */
494 struct ospf_route
*cur_or
;
496 route_unlock_node(rn
);
500 if (IS_DEBUG_OSPF_EVENT
)
502 "ospf_intra_add_stub(): "
503 "another route to the same prefix found with cost %u",
506 /* Compare this distance to the current best cost to the stub
507 network. This is done by looking up the stub network's
508 current routing table entry. If the calculated distance D is
509 larger, go on to examine the next stub network link in the
511 if (cost
> cur_or
->cost
) {
512 if (IS_DEBUG_OSPF_EVENT
)
514 "ospf_intra_add_stub(): old route is better, exit");
518 /* (2) If this step is reached, the stub network's routing table
519 entry must be updated. Calculate the set of next hops that
520 would result from using the stub network link. This
521 calculation is shown in Section 16.1.1; input to this
522 calculation is the destination (the stub network) and the
523 parent vertex (the router vertex). If the distance D is the
524 same as the current routing table cost, simply add this set
525 of next hops to the routing table entry's list of next hops.
526 In this case, the routing table already has a Link State
527 Origin. If this Link State Origin is a router-LSA whose Link
528 State ID is smaller than V's Router ID, reset the Link State
529 Origin to V's router-LSA. */
531 if (cost
== cur_or
->cost
) {
532 if (IS_DEBUG_OSPF_EVENT
)
534 "ospf_intra_add_stub(): routes are equal, merge");
536 ospf_route_copy_nexthops_from_vertex(cur_or
, v
);
538 if (IPV4_ADDR_CMP(&cur_or
->u
.std
.origin
->id
,
541 cur_or
->u
.std
.origin
= (struct lsa_header
*)lsa
;
545 /* Otherwise D is smaller than the routing table cost.
546 Overwrite the current routing table entry by setting the
547 routing table entry's cost to D, and by setting the entry's
548 list of next hops to the newly calculated set. Set the
549 routing table entry's Link State Origin to V's router-LSA.
550 Then go on to examine the next stub network link. */
552 if (cost
< cur_or
->cost
) {
553 if (IS_DEBUG_OSPF_EVENT
)
555 "ospf_intra_add_stub(): new route is better, set it");
559 list_delete_all_node(cur_or
->paths
);
561 ospf_route_copy_nexthops_from_vertex(cur_or
, v
);
563 cur_or
->u
.std
.origin
= (struct lsa_header
*)lsa
;
568 if (IS_DEBUG_OSPF_EVENT
)
569 zlog_debug("ospf_intra_add_stub(): installing new route");
571 or = ospf_route_new();
574 or->u
.std
.area_id
= area
->area_id
;
575 or->u
.std
.external_routing
= area
->external_routing
;
576 or->path_type
= OSPF_PATH_INTRA_AREA
;
578 or->type
= OSPF_DESTINATION_NETWORK
;
579 or->u
.std
.origin
= (struct lsa_header
*)lsa
;
581 /* Nexthop is depend on connection type. */
582 if (v
!= area
->spf
) {
583 if (IS_DEBUG_OSPF_EVENT
)
585 "ospf_intra_add_stub(): this network is on remote router");
586 ospf_route_copy_nexthops_from_vertex(or, v
);
588 if (IS_DEBUG_OSPF_EVENT
)
590 "ospf_intra_add_stub(): this network is on this router");
592 if ((oi
= ospf_if_lookup_by_lsa_pos(area
, lsa_pos
))) {
593 if (IS_DEBUG_OSPF_EVENT
)
595 "ospf_intra_add_stub(): the interface is %s",
598 path
= ospf_path_new();
599 path
->nexthop
.s_addr
= 0;
600 path
->ifindex
= oi
->ifp
->ifindex
;
601 if (CHECK_FLAG(oi
->connected
->flags
,
602 ZEBRA_IFA_UNNUMBERED
))
603 path
->unnumbered
= 1;
604 listnode_add(or->paths
, path
);
606 if (IS_DEBUG_OSPF_EVENT
)
608 "ospf_intra_add_stub(): where's the interface ?");
614 if (IS_DEBUG_OSPF_EVENT
)
615 zlog_debug("ospf_intra_add_stub(): Stop");
618 const char *ospf_path_type_str
[] = {"unknown-type", "intra-area", "inter-area",
619 "type1-external", "type2-external"};
621 void ospf_route_table_dump(struct route_table
*rt
)
623 struct route_node
*rn
;
624 struct ospf_route
* or ;
627 struct listnode
*pnode
;
628 struct ospf_path
*path
;
631 zlog_debug ("Type Dest Area Path Type Cost Next Adv.");
632 zlog_debug (" Hop(s) Router(s)");
635 zlog_debug("========== OSPF routing table ==========");
636 for (rn
= route_top(rt
); rn
; rn
= route_next(rn
))
637 if ((or = rn
->info
) != NULL
) {
638 if (or->type
== OSPF_DESTINATION_NETWORK
) {
639 zlog_debug("N %s/%d\t%s\t%s\t%d",
640 inet_ntop(AF_INET
, &rn
->p
.u
.prefix4
,
644 & or->u
.std
.area_id
, buf2
,
646 ospf_path_type_str
[or->path_type
],
648 for (ALL_LIST_ELEMENTS_RO(or->paths
, pnode
,
651 inet_ntoa(path
->nexthop
));
653 zlog_debug("R %s\t%s\t%s\t%d",
654 inet_ntop(AF_INET
, &rn
->p
.u
.prefix4
,
657 & or->u
.std
.area_id
, buf2
,
659 ospf_path_type_str
[or->path_type
],
662 zlog_debug("========================================");
665 /* This is 16.4.1 implementation.
666 o Intra-area paths using non-backbone areas are always the most preferred.
667 o The other paths, intra-area backbone paths and inter-area paths,
668 are of equal preference. */
669 static int ospf_asbr_route_cmp(struct ospf
*ospf
, struct ospf_route
*r1
,
670 struct ospf_route
*r2
)
672 u_char r1_type
, r2_type
;
674 r1_type
= r1
->path_type
;
675 r2_type
= r2
->path_type
;
677 /* r1/r2 itself is backbone, and it's Inter-area path. */
678 if (OSPF_IS_AREA_ID_BACKBONE(r1
->u
.std
.area_id
))
679 r1_type
= OSPF_PATH_INTER_AREA
;
680 if (OSPF_IS_AREA_ID_BACKBONE(r2
->u
.std
.area_id
))
681 r2_type
= OSPF_PATH_INTER_AREA
;
683 return (r1_type
- r2_type
);
686 /* Compare two routes.
687 ret < 0 -- r1 is better.
688 ret == 0 -- r1 and r2 are the same.
689 ret > 0 -- r2 is better. */
690 int ospf_route_cmp(struct ospf
*ospf
, struct ospf_route
*r1
,
691 struct ospf_route
*r2
)
695 /* Path types of r1 and r2 are not the same. */
696 if ((ret
= (r1
->path_type
- r2
->path_type
)))
699 if (IS_DEBUG_OSPF_EVENT
)
700 zlog_debug("Route[Compare]: Path types are the same.");
701 /* Path types are the same, compare any cost. */
702 switch (r1
->path_type
) {
703 case OSPF_PATH_INTRA_AREA
:
704 case OSPF_PATH_INTER_AREA
:
706 case OSPF_PATH_TYPE1_EXTERNAL
:
707 if (!CHECK_FLAG(ospf
->config
, OSPF_RFC1583_COMPATIBLE
)) {
708 ret
= ospf_asbr_route_cmp(ospf
, r1
->u
.ext
.asbr
,
714 case OSPF_PATH_TYPE2_EXTERNAL
:
715 if ((ret
= (r1
->u
.ext
.type2_cost
- r2
->u
.ext
.type2_cost
)))
718 if (!CHECK_FLAG(ospf
->config
, OSPF_RFC1583_COMPATIBLE
)) {
719 ret
= ospf_asbr_route_cmp(ospf
, r1
->u
.ext
.asbr
,
727 /* Anyway, compare the costs. */
728 return (r1
->cost
- r2
->cost
);
731 static int ospf_path_exist(struct list
*plist
, struct in_addr nexthop
,
732 struct ospf_interface
*oi
)
734 struct listnode
*node
, *nnode
;
735 struct ospf_path
*path
;
737 for (ALL_LIST_ELEMENTS(plist
, node
, nnode
, path
))
738 if (IPV4_ADDR_SAME(&path
->nexthop
, &nexthop
)
739 && path
->ifindex
== oi
->ifp
->ifindex
)
745 void ospf_route_copy_nexthops_from_vertex(struct ospf_route
*to
,
748 struct listnode
*node
;
749 struct ospf_path
*path
;
750 struct vertex_nexthop
*nexthop
;
751 struct vertex_parent
*vp
;
755 for (ALL_LIST_ELEMENTS_RO(v
->parents
, node
, vp
)) {
756 nexthop
= vp
->nexthop
;
758 if (nexthop
->oi
!= NULL
) {
759 if (!ospf_path_exist(to
->paths
, nexthop
->router
,
761 path
= ospf_path_new();
762 path
->nexthop
= nexthop
->router
;
763 path
->ifindex
= nexthop
->oi
->ifp
->ifindex
;
764 if (CHECK_FLAG(nexthop
->oi
->connected
->flags
,
765 ZEBRA_IFA_UNNUMBERED
))
766 path
->unnumbered
= 1;
767 listnode_add(to
->paths
, path
);
773 struct ospf_path
*ospf_path_lookup(struct list
*plist
, struct ospf_path
*path
)
775 struct listnode
*node
;
776 struct ospf_path
*op
;
778 for (ALL_LIST_ELEMENTS_RO(plist
, node
, op
)) {
779 if (!IPV4_ADDR_SAME(&op
->nexthop
, &path
->nexthop
))
781 if (!IPV4_ADDR_SAME(&op
->adv_router
, &path
->adv_router
))
783 if (op
->ifindex
!= path
->ifindex
)
790 void ospf_route_copy_nexthops(struct ospf_route
*to
, struct list
*from
)
792 struct listnode
*node
, *nnode
;
793 struct ospf_path
*path
;
797 for (ALL_LIST_ELEMENTS(from
, node
, nnode
, path
))
798 /* The same routes are just discarded. */
799 if (!ospf_path_lookup(to
->paths
, path
))
800 listnode_add(to
->paths
, ospf_path_dup(path
));
803 void ospf_route_subst_nexthops(struct ospf_route
*to
, struct list
*from
)
806 list_delete_all_node(to
->paths
);
807 ospf_route_copy_nexthops(to
, from
);
810 void ospf_route_subst(struct route_node
*rn
, struct ospf_route
*new_or
,
811 struct ospf_route
*over
)
814 ospf_route_free(rn
->info
);
816 ospf_route_copy_nexthops(new_or
, over
->paths
);
818 route_unlock_node(rn
);
821 void ospf_route_add(struct route_table
*rt
, struct prefix_ipv4
*p
,
822 struct ospf_route
*new_or
, struct ospf_route
*over
)
824 struct route_node
*rn
;
826 rn
= route_node_get(rt
, (struct prefix
*)p
);
828 ospf_route_copy_nexthops(new_or
, over
->paths
);
831 if (IS_DEBUG_OSPF_EVENT
)
832 zlog_debug("ospf_route_add(): something's wrong !");
833 route_unlock_node(rn
);
840 void ospf_prune_unreachable_networks(struct route_table
*rt
)
842 struct route_node
*rn
, *next
;
843 struct ospf_route
* or ;
845 if (IS_DEBUG_OSPF_EVENT
)
846 zlog_debug("Pruning unreachable networks");
848 for (rn
= route_top(rt
); rn
; rn
= next
) {
849 next
= route_next(rn
);
850 if (rn
->info
!= NULL
) {
852 if (listcount(or->paths
) == 0) {
853 if (IS_DEBUG_OSPF_EVENT
)
854 zlog_debug("Pruning route to %s/%d",
855 inet_ntoa(rn
->p
.u
.prefix4
),
860 route_unlock_node(rn
);
866 void ospf_prune_unreachable_routers(struct route_table
*rtrs
)
868 struct route_node
*rn
, *next
;
869 struct ospf_route
* or ;
870 struct listnode
*node
, *nnode
;
873 if (IS_DEBUG_OSPF_EVENT
)
874 zlog_debug("Pruning unreachable routers");
876 for (rn
= route_top(rtrs
); rn
; rn
= next
) {
877 next
= route_next(rn
);
878 if ((paths
= rn
->info
) == NULL
)
881 for (ALL_LIST_ELEMENTS(paths
, node
, nnode
, or)) {
882 if (listcount(or->paths
) == 0) {
883 if (IS_DEBUG_OSPF_EVENT
) {
884 zlog_debug("Pruning route to rtr %s",
885 inet_ntoa(rn
->p
.u
.prefix4
));
888 inet_ntoa(or->u
.std
.area_id
));
891 listnode_delete(paths
, or);
896 if (listcount(paths
) == 0) {
897 if (IS_DEBUG_OSPF_EVENT
)
898 zlog_debug("Pruning router node %s",
899 inet_ntoa(rn
->p
.u
.prefix4
));
903 route_unlock_node(rn
);
908 int ospf_add_discard_route(struct route_table
*rt
, struct ospf_area
*area
,
909 struct prefix_ipv4
*p
)
911 struct route_node
*rn
;
912 struct ospf_route
* or, *new_or
;
914 rn
= route_node_get(rt
, (struct prefix
*)p
);
917 if (IS_DEBUG_OSPF_EVENT
)
919 "ospf_add_discard_route(): router installation error");
923 if (rn
->info
) /* If the route to the same destination is found */
925 route_unlock_node(rn
);
929 if (or->path_type
== OSPF_PATH_INTRA_AREA
) {
930 if (IS_DEBUG_OSPF_EVENT
)
932 "ospf_add_discard_route(): "
933 "an intra-area route exists");
937 if (or->type
== OSPF_DESTINATION_DISCARD
) {
938 if (IS_DEBUG_OSPF_EVENT
)
940 "ospf_add_discard_route(): "
941 "discard entry already installed");
945 ospf_route_free(rn
->info
);
948 if (IS_DEBUG_OSPF_EVENT
)
950 "ospf_add_discard_route(): "
952 inet_ntoa(p
->prefix
), p
->prefixlen
);
954 new_or
= ospf_route_new();
955 new_or
->type
= OSPF_DESTINATION_DISCARD
;
956 new_or
->id
.s_addr
= 0;
958 new_or
->u
.std
.area_id
= area
->area_id
;
959 new_or
->u
.std
.external_routing
= area
->external_routing
;
960 new_or
->path_type
= OSPF_PATH_INTER_AREA
;
963 ospf_zebra_add_discard(p
);
968 void ospf_delete_discard_route(struct route_table
*rt
, struct prefix_ipv4
*p
)
970 struct route_node
*rn
;
971 struct ospf_route
* or ;
973 if (IS_DEBUG_OSPF_EVENT
)
975 "ospf_delete_discard_route(): "
977 inet_ntoa(p
->prefix
), p
->prefixlen
);
979 rn
= route_node_lookup(rt
, (struct prefix
*)p
);
982 if (IS_DEBUG_OSPF_EVENT
)
984 "ospf_delete_discard_route(): no route found");
990 if (or->path_type
== OSPF_PATH_INTRA_AREA
) {
991 if (IS_DEBUG_OSPF_EVENT
)
993 "ospf_delete_discard_route(): "
994 "an intra-area route exists");
998 if (or->type
!= OSPF_DESTINATION_DISCARD
) {
999 if (IS_DEBUG_OSPF_EVENT
)
1001 "ospf_delete_discard_route(): "
1002 "not a discard entry");
1006 /* free the route entry and the route node */
1007 ospf_route_free(rn
->info
);
1010 route_unlock_node(rn
);
1011 route_unlock_node(rn
);
1013 /* remove the discard entry from the rib */
1014 ospf_zebra_delete_discard(p
);