]>
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(void)
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(void)
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;
76 new = ospf_path_new();
77 memcpy(new, path
, sizeof(struct ospf_path
));
79 /* optional TI-LFA backup paths */
80 if (path
->srni
.backup_label_stack
) {
81 memsize
= sizeof(struct mpls_label_stack
)
82 + (sizeof(mpls_label_t
)
83 * path
->srni
.backup_label_stack
->num_labels
);
84 new->srni
.backup_label_stack
=
85 XCALLOC(MTYPE_OSPF_PATH
, memsize
);
86 memcpy(new->srni
.backup_label_stack
,
87 path
->srni
.backup_label_stack
, memsize
);
93 void ospf_path_free(struct ospf_path
*op
)
95 /* optional TI-LFA backup paths */
96 if (op
->srni
.backup_label_stack
)
97 XFREE(MTYPE_OSPF_PATH
, op
->srni
.backup_label_stack
);
99 XFREE(MTYPE_OSPF_PATH
, op
);
102 void ospf_route_delete(struct ospf
*ospf
, 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
) {
109 if (or->type
== OSPF_DESTINATION_NETWORK
)
111 ospf
, (struct prefix_ipv4
*)&rn
->p
, or);
112 else if (or->type
== OSPF_DESTINATION_DISCARD
)
113 ospf_zebra_delete_discard(
114 ospf
, (struct prefix_ipv4
*)&rn
->p
);
118 void ospf_route_table_free(struct route_table
*rt
)
120 struct route_node
*rn
;
121 struct ospf_route
* or ;
123 for (rn
= route_top(rt
); rn
; rn
= route_next(rn
))
124 if ((or = rn
->info
) != NULL
) {
128 route_unlock_node(rn
);
131 route_table_finish(rt
);
134 /* If a prefix exists in the new routing table, then return 1,
135 otherwise return 0. Since the ZEBRA-RIB does an implicit
136 withdraw, it is not necessary to send a delete, an add later
137 will act like an implicit delete. */
138 static int ospf_route_exist_new_table(struct route_table
*rt
,
139 struct prefix_ipv4
*prefix
)
141 struct route_node
*rn
;
146 rn
= route_node_lookup(rt
, (struct prefix
*)prefix
);
150 route_unlock_node(rn
);
159 static int ospf_route_backup_path_same(struct sr_nexthop_info
*srni1
,
160 struct sr_nexthop_info
*srni2
)
162 struct mpls_label_stack
*ls1
, *ls2
;
165 ls1
= srni1
->backup_label_stack
;
166 ls2
= srni2
->backup_label_stack
;
171 if ((ls1
&& !ls2
) || (!ls1
&& ls2
))
174 if (ls1
->num_labels
!= ls2
->num_labels
)
177 for (label_count
= 0; label_count
< ls1
->num_labels
; label_count
++) {
178 if (ls1
->label
[label_count
] != ls2
->label
[label_count
])
182 if (!IPV4_ADDR_SAME(&srni1
->backup_nexthop
, &srni2
->backup_nexthop
))
188 /* If a prefix and a nexthop match any route in the routing table,
189 then return 1, otherwise return 0. */
190 int ospf_route_match_same(struct route_table
*rt
, struct prefix_ipv4
*prefix
,
191 struct ospf_route
*newor
)
193 struct route_node
*rn
;
194 struct ospf_route
* or ;
195 struct ospf_path
*op
;
196 struct ospf_path
*newop
;
203 rn
= route_node_lookup(rt
, (struct prefix
*)prefix
);
204 if (!rn
|| !rn
->info
)
207 route_unlock_node(rn
);
210 if (or->type
== newor
->type
&& or->cost
== newor
->cost
) {
211 if (or->type
== OSPF_DESTINATION_NETWORK
) {
212 if (or->paths
->count
!= newor
->paths
->count
)
215 /* Check each path. */
216 for (n1
= listhead(or->paths
),
217 n2
= listhead(newor
->paths
);
218 n1
&& n2
; n1
= listnextnode_unchecked(n1
),
219 n2
= listnextnode_unchecked(n2
)) {
220 op
= listgetdata(n1
);
221 newop
= listgetdata(n2
);
223 if (!IPV4_ADDR_SAME(&op
->nexthop
,
226 if (op
->ifindex
!= newop
->ifindex
)
229 /* check TI-LFA backup paths */
230 if (!ospf_route_backup_path_same(&op
->srni
,
235 } else if (prefix_same(&rn
->p
, (struct prefix
*)prefix
))
241 /* delete routes generated from AS-External routes if there is a inter/intra
244 static void ospf_route_delete_same_ext(struct ospf
*ospf
,
245 struct route_table
*external_routes
,
246 struct route_table
*routes
)
248 struct route_node
*rn
, *ext_rn
;
250 if ((external_routes
== NULL
) || (routes
== NULL
))
253 /* Remove deleted routes */
254 for (rn
= route_top(routes
); rn
; rn
= route_next(rn
)) {
255 if (rn
&& rn
->info
) {
256 struct prefix_ipv4
*p
= (struct prefix_ipv4
*)(&rn
->p
);
257 if ((ext_rn
= route_node_lookup(external_routes
,
258 (struct prefix
*)p
))) {
260 ospf_zebra_delete(ospf
, p
,
262 ospf_route_free(ext_rn
->info
);
265 route_unlock_node(ext_rn
);
271 /* rt: Old, cmprt: New */
272 static void ospf_route_delete_uniq(struct ospf
*ospf
, struct route_table
*rt
,
273 struct route_table
*cmprt
)
275 struct route_node
*rn
;
276 struct ospf_route
* or ;
278 for (rn
= route_top(rt
); rn
; rn
= route_next(rn
))
279 if ((or = rn
->info
) != NULL
)
280 if (or->path_type
== OSPF_PATH_INTRA_AREA
||
281 or->path_type
== OSPF_PATH_INTER_AREA
) {
282 if (or->type
== OSPF_DESTINATION_NETWORK
) {
283 if (!ospf_route_exist_new_table(
285 (struct prefix_ipv4
*)&rn
292 } else if (or->type
== OSPF_DESTINATION_DISCARD
)
293 if (!ospf_route_exist_new_table(
295 (struct prefix_ipv4
*)&rn
297 ospf_zebra_delete_discard(
304 /* Install routes to table. */
305 void ospf_route_install(struct ospf
*ospf
, struct route_table
*rt
)
307 struct route_node
*rn
;
308 struct ospf_route
* or ;
310 /* rt contains new routing table, new_table contains an old one.
313 ospf_route_table_free(ospf
->old_table
);
315 ospf
->old_table
= ospf
->new_table
;
316 ospf
->new_table
= rt
;
318 /* Delete old routes. */
320 ospf_route_delete_uniq(ospf
, ospf
->old_table
, rt
);
321 if (ospf
->old_external_route
)
322 ospf_route_delete_same_ext(ospf
, ospf
->old_external_route
, rt
);
324 /* Install new routes. */
325 for (rn
= route_top(rt
); rn
; rn
= route_next(rn
))
326 if ((or = rn
->info
) != NULL
) {
327 if (or->type
== OSPF_DESTINATION_NETWORK
) {
328 if (!ospf_route_match_same(
330 (struct prefix_ipv4
*)&rn
->p
, or))
333 (struct prefix_ipv4
*)&rn
->p
,
335 } else if (or->type
== OSPF_DESTINATION_DISCARD
)
336 if (!ospf_route_match_same(
338 (struct prefix_ipv4
*)&rn
->p
, or))
339 ospf_zebra_add_discard(
341 (struct prefix_ipv4
*)&rn
->p
);
345 /* RFC2328 16.1. (4). For "router". */
346 void ospf_intra_add_router(struct route_table
*rt
, struct vertex
*v
,
347 struct ospf_area
*area
)
349 struct route_node
*rn
;
350 struct ospf_route
* or ;
351 struct prefix_ipv4 p
;
352 struct router_lsa
*lsa
;
354 if (IS_DEBUG_OSPF_EVENT
)
355 zlog_debug("ospf_intra_add_router: Start");
357 lsa
= (struct router_lsa
*)v
->lsa
;
359 if (IS_DEBUG_OSPF_EVENT
)
360 zlog_debug("ospf_intra_add_router: LS ID: %pI4",
363 if (!OSPF_IS_AREA_BACKBONE(area
))
364 ospf_vl_up_check(area
, lsa
->header
.id
, v
);
366 if (!CHECK_FLAG(lsa
->flags
, ROUTER_LSA_SHORTCUT
))
367 area
->shortcut_capability
= 0;
369 /* If the newly added vertex is an area border router or AS boundary
370 router, a routing table entry is added whose destination type is
372 if (!IS_ROUTER_LSA_BORDER(lsa
) && !IS_ROUTER_LSA_EXTERNAL(lsa
)) {
373 if (IS_DEBUG_OSPF_EVENT
)
375 "ospf_intra_add_router: this router is neither ASBR nor ABR, skipping it");
379 /* Update ABR and ASBR count in this area. */
380 if (IS_ROUTER_LSA_BORDER(lsa
))
382 if (IS_ROUTER_LSA_EXTERNAL(lsa
))
385 /* The Options field found in the associated router-LSA is copied
386 into the routing table entry's Optional capabilities field. Call
387 the newly added vertex Router X. */
388 or = ospf_route_new();
391 or->u
.std
.area_id
= area
->area_id
;
392 or->u
.std
.external_routing
= area
->external_routing
;
393 or->path_type
= OSPF_PATH_INTRA_AREA
;
394 or->cost
= v
->distance
;
395 or->type
= OSPF_DESTINATION_ROUTER
;
396 or->u
.std
.origin
= (struct lsa_header
*)lsa
;
397 or->u
.std
.options
= lsa
->header
.options
;
398 or->u
.std
.flags
= lsa
->flags
;
400 /* If Router X is the endpoint of one of the calculating router's
401 virtual links, and the virtual link uses Area A as Transit area:
402 the virtual link is declared up, the IP address of the virtual
403 interface is set to the IP address of the outgoing interface
404 calculated above for Router X, and the virtual neighbor's IP
405 address is set to Router X's interface address (contained in
406 Router X's router-LSA) that points back to the root of the
407 shortest- path tree; equivalently, this is the interface that
408 points back to Router X's parent vertex on the shortest-path tree
409 (similar to the calculation in Section 16.1.1). */
413 p
.prefixlen
= IPV4_MAX_BITLEN
;
416 if (IS_DEBUG_OSPF_EVENT
)
417 zlog_debug("ospf_intra_add_router: talking about %pFX", &p
);
419 rn
= route_node_get(rt
, (struct prefix
*)&p
);
421 /* Note that we keep all routes to ABRs and ASBRs, not only the best */
422 if (rn
->info
== NULL
)
423 rn
->info
= list_new();
425 route_unlock_node(rn
);
427 ospf_route_copy_nexthops_from_vertex(area
, or, v
);
429 listnode_add(rn
->info
, or);
431 if (IS_DEBUG_OSPF_EVENT
)
432 zlog_debug("ospf_intra_add_router: Stop");
435 /* RFC2328 16.1. (4). For transit network. */
436 void ospf_intra_add_transit(struct route_table
*rt
, struct vertex
*v
,
437 struct ospf_area
*area
)
439 struct route_node
*rn
;
440 struct ospf_route
* or ;
441 struct prefix_ipv4 p
;
442 struct network_lsa
*lsa
;
444 lsa
= (struct network_lsa
*)v
->lsa
;
446 /* If the newly added vertex is a transit network, the routing table
447 entry for the network is located. The entry's Destination ID is
448 the IP network number, which can be obtained by masking the
449 Vertex ID (Link State ID) with its associated subnet mask (found
450 in the body of the associated network-LSA). */
453 p
.prefixlen
= ip_masklen(lsa
->mask
);
456 rn
= route_node_get(rt
, (struct prefix
*)&p
);
458 /* If the routing table entry already exists (i.e., there is already
459 an intra-area route to the destination installed in the routing
460 table), multiple vertices have mapped to the same IP network.
461 For example, this can occur when a new Designated Router is being
462 established. In this case, the current routing table entry
463 should be overwritten if and only if the newly found path is just
464 as short and the current routing table entry's Link State Origin
465 has a smaller Link State ID than the newly added vertex' LSA. */
467 struct ospf_route
*cur_or
;
469 route_unlock_node(rn
);
472 if (v
->distance
> cur_or
->cost
473 || IPV4_ADDR_CMP(&cur_or
->u
.std
.origin
->id
, &lsa
->header
.id
)
477 ospf_route_free(rn
->info
);
480 or = ospf_route_new();
483 or->u
.std
.area_id
= area
->area_id
;
484 or->u
.std
.external_routing
= area
->external_routing
;
485 or->path_type
= OSPF_PATH_INTRA_AREA
;
486 or->cost
= v
->distance
;
487 or->type
= OSPF_DESTINATION_NETWORK
;
488 or->u
.std
.origin
= (struct lsa_header
*)lsa
;
490 ospf_route_copy_nexthops_from_vertex(area
, or, v
);
495 /* RFC2328 16.1. second stage. */
496 void ospf_intra_add_stub(struct route_table
*rt
, struct router_lsa_link
*link
,
497 struct vertex
*v
, struct ospf_area
*area
,
498 int parent_is_root
, int lsa_pos
)
501 struct route_node
*rn
;
502 struct ospf_route
* or ;
503 struct prefix_ipv4 p
;
504 struct router_lsa
*lsa
;
505 struct ospf_interface
*oi
= NULL
;
506 struct ospf_path
*path
;
508 if (IS_DEBUG_OSPF_EVENT
)
509 zlog_debug("ospf_intra_add_stub(): Start");
511 lsa
= (struct router_lsa
*)v
->lsa
;
514 p
.prefix
= link
->link_id
;
515 p
.prefixlen
= ip_masklen(link
->link_data
);
518 if (IS_DEBUG_OSPF_EVENT
)
519 zlog_debug("ospf_intra_add_stub(): processing route to %pFX",
522 /* (1) Calculate the distance D of stub network from the root. D is
523 equal to the distance from the root to the router vertex
524 (calculated in stage 1), plus the stub network link's advertised
526 cost
= v
->distance
+ ntohs(link
->m
[0].metric
);
528 if (IS_DEBUG_OSPF_EVENT
)
530 "ospf_intra_add_stub(): calculated cost is %d + %d = %d",
531 v
->distance
, ntohs(link
->m
[0].metric
), cost
);
533 /* PtP links with /32 masks adds host routes to remote, directly
534 * connected hosts, see RFC 2328, 12.4.1.1, Option 1.
535 * Such routes can just be ignored for the sake of tidyness.
537 if (parent_is_root
&& link
->link_data
.s_addr
== 0xffffffff
538 && ospf_if_lookup_by_local_addr(area
->ospf
, NULL
, link
->link_id
)) {
539 if (IS_DEBUG_OSPF_EVENT
)
540 zlog_debug("%s: ignoring host route %pI4/32 to self.",
541 __func__
, &link
->link_id
);
545 rn
= route_node_get(rt
, (struct prefix
*)&p
);
547 /* Lookup current routing table. */
549 struct ospf_route
*cur_or
;
551 route_unlock_node(rn
);
555 if (IS_DEBUG_OSPF_EVENT
)
557 "ospf_intra_add_stub(): another route to the same prefix found with cost %u",
560 /* Compare this distance to the current best cost to the stub
561 network. This is done by looking up the stub network's
562 current routing table entry. If the calculated distance D is
563 larger, go on to examine the next stub network link in the
565 if (cost
> cur_or
->cost
) {
566 if (IS_DEBUG_OSPF_EVENT
)
568 "ospf_intra_add_stub(): old route is better, exit");
572 /* (2) If this step is reached, the stub network's routing table
573 entry must be updated. Calculate the set of next hops that
574 would result from using the stub network link. This
575 calculation is shown in Section 16.1.1; input to this
576 calculation is the destination (the stub network) and the
577 parent vertex (the router vertex). If the distance D is the
578 same as the current routing table cost, simply add this set
579 of next hops to the routing table entry's list of next hops.
580 In this case, the routing table already has a Link State
581 Origin. If this Link State Origin is a router-LSA whose Link
582 State ID is smaller than V's Router ID, reset the Link State
583 Origin to V's router-LSA. */
585 if (cost
== cur_or
->cost
) {
586 if (IS_DEBUG_OSPF_EVENT
)
588 "ospf_intra_add_stub(): routes are equal, merge");
590 ospf_route_copy_nexthops_from_vertex(area
, cur_or
, v
);
592 if (IPV4_ADDR_CMP(&cur_or
->u
.std
.origin
->id
,
595 cur_or
->u
.std
.origin
= (struct lsa_header
*)lsa
;
599 /* Otherwise D is smaller than the routing table cost.
600 Overwrite the current routing table entry by setting the
601 routing table entry's cost to D, and by setting the entry's
602 list of next hops to the newly calculated set. Set the
603 routing table entry's Link State Origin to V's router-LSA.
604 Then go on to examine the next stub network link. */
606 if (cost
< cur_or
->cost
) {
607 if (IS_DEBUG_OSPF_EVENT
)
609 "ospf_intra_add_stub(): new route is better, set it");
613 list_delete_all_node(cur_or
->paths
);
615 ospf_route_copy_nexthops_from_vertex(area
, cur_or
, v
);
617 cur_or
->u
.std
.origin
= (struct lsa_header
*)lsa
;
622 if (IS_DEBUG_OSPF_EVENT
)
623 zlog_debug("ospf_intra_add_stub(): installing new route");
625 or = ospf_route_new();
628 or->u
.std
.area_id
= area
->area_id
;
629 or->u
.std
.external_routing
= area
->external_routing
;
630 or->path_type
= OSPF_PATH_INTRA_AREA
;
632 or->type
= OSPF_DESTINATION_NETWORK
;
633 or->u
.std
.origin
= (struct lsa_header
*)lsa
;
635 /* Nexthop is depend on connection type. */
636 if (v
!= area
->spf
) {
637 if (IS_DEBUG_OSPF_EVENT
)
639 "ospf_intra_add_stub(): this network is on remote router");
640 ospf_route_copy_nexthops_from_vertex(area
, or, v
);
642 if (IS_DEBUG_OSPF_EVENT
)
644 "ospf_intra_add_stub(): this network is on this router");
647 * Only deal with interface data when we
650 if (!area
->spf_dry_run
)
651 oi
= ospf_if_lookup_by_lsa_pos(area
, lsa_pos
);
653 if (oi
|| area
->spf_dry_run
) {
654 if (IS_DEBUG_OSPF_EVENT
)
656 "ospf_intra_add_stub(): the lsa pos is %d",
659 path
= ospf_path_new();
660 path
->nexthop
.s_addr
= INADDR_ANY
;
663 path
->ifindex
= oi
->ifp
->ifindex
;
664 if (CHECK_FLAG(oi
->connected
->flags
,
665 ZEBRA_IFA_UNNUMBERED
))
666 path
->unnumbered
= 1;
669 listnode_add(or->paths
, path
);
671 if (IS_DEBUG_OSPF_EVENT
)
673 "ospf_intra_add_stub(): where's the interface ?");
679 if (IS_DEBUG_OSPF_EVENT
)
680 zlog_debug("ospf_intra_add_stub(): Stop");
683 static const char *const ospf_path_type_str
[] = {
684 "unknown-type", "intra-area", "inter-area", "type1-external",
688 void ospf_route_table_dump(struct route_table
*rt
)
690 struct route_node
*rn
;
691 struct ospf_route
* or ;
692 struct listnode
*pnode
;
693 struct ospf_path
*path
;
695 zlog_debug("========== OSPF routing table ==========");
696 for (rn
= route_top(rt
); rn
; rn
= route_next(rn
))
697 if ((or = rn
->info
) != NULL
) {
698 if (or->type
== OSPF_DESTINATION_NETWORK
) {
699 zlog_debug("N %-18pFX %-15pI4 %s %d", &rn
->p
,
701 ospf_path_type_str
[or->path_type
],
703 for (ALL_LIST_ELEMENTS_RO(or->paths
, pnode
,
705 zlog_debug(" -> %pI4",
708 zlog_debug("R %-18pI4 %-15pI4 %s %d",
711 ospf_path_type_str
[or->path_type
],
714 zlog_debug("========================================");
717 /* This is 16.4.1 implementation.
718 o Intra-area paths using non-backbone areas are always the most preferred.
719 o The other paths, intra-area backbone paths and inter-area paths,
720 are of equal preference. */
721 static int ospf_asbr_route_cmp(struct ospf
*ospf
, struct ospf_route
*r1
,
722 struct ospf_route
*r2
)
724 uint8_t r1_type
, r2_type
;
726 r1_type
= r1
->path_type
;
727 r2_type
= r2
->path_type
;
729 /* r1/r2 itself is backbone, and it's Inter-area path. */
730 if (OSPF_IS_AREA_ID_BACKBONE(r1
->u
.std
.area_id
))
731 r1_type
= OSPF_PATH_INTER_AREA
;
732 if (OSPF_IS_AREA_ID_BACKBONE(r2
->u
.std
.area_id
))
733 r2_type
= OSPF_PATH_INTER_AREA
;
735 return (r1_type
- r2_type
);
738 /* Compare two routes.
739 ret < 0 -- r1 is better.
740 ret == 0 -- r1 and r2 are the same.
741 ret > 0 -- r2 is better. */
742 int ospf_route_cmp(struct ospf
*ospf
, struct ospf_route
*r1
,
743 struct ospf_route
*r2
)
747 /* Path types of r1 and r2 are not the same. */
748 if ((ret
= (r1
->path_type
- r2
->path_type
)))
751 if (IS_DEBUG_OSPF_EVENT
)
752 zlog_debug("Route[Compare]: Path types are the same.");
753 /* Path types are the same, compare any cost. */
754 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
)) {
760 ret
= ospf_asbr_route_cmp(ospf
, r1
->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
)) {
771 ret
= ospf_asbr_route_cmp(ospf
, r1
->u
.ext
.asbr
,
779 /* Anyway, compare the costs. */
780 return (r1
->cost
- r2
->cost
);
783 static int ospf_path_exist(struct list
*plist
, struct in_addr nexthop
,
784 struct ospf_interface
*oi
)
786 struct listnode
*node
, *nnode
;
787 struct ospf_path
*path
;
789 for (ALL_LIST_ELEMENTS(plist
, node
, nnode
, path
))
790 if (IPV4_ADDR_SAME(&path
->nexthop
, &nexthop
)
791 && path
->ifindex
== oi
->ifp
->ifindex
)
797 void ospf_route_copy_nexthops_from_vertex(struct ospf_area
*area
,
798 struct ospf_route
*to
,
801 struct listnode
*node
;
802 struct ospf_path
*path
;
803 struct vertex_nexthop
*nexthop
;
804 struct vertex_parent
*vp
;
805 struct ospf_interface
*oi
= NULL
;
809 for (ALL_LIST_ELEMENTS_RO(v
->parents
, node
, vp
)) {
810 nexthop
= vp
->nexthop
;
813 * Only deal with interface data when we
816 if (!area
->spf_dry_run
)
817 oi
= ospf_if_lookup_by_lsa_pos(area
, nexthop
->lsa_pos
);
819 if ((oi
&& !ospf_path_exist(to
->paths
, nexthop
->router
, oi
))
820 || area
->spf_dry_run
) {
821 path
= ospf_path_new();
822 path
->nexthop
= nexthop
->router
;
823 path
->adv_router
= v
->id
;
826 path
->ifindex
= oi
->ifp
->ifindex
;
827 if (CHECK_FLAG(oi
->connected
->flags
,
828 ZEBRA_IFA_UNNUMBERED
))
829 path
->unnumbered
= 1;
832 listnode_add(to
->paths
, path
);
837 struct ospf_path
*ospf_path_lookup(struct list
*plist
, struct ospf_path
*path
)
839 struct listnode
*node
;
840 struct ospf_path
*op
;
842 for (ALL_LIST_ELEMENTS_RO(plist
, node
, op
)) {
843 if (!IPV4_ADDR_SAME(&op
->nexthop
, &path
->nexthop
))
845 if (!IPV4_ADDR_SAME(&op
->adv_router
, &path
->adv_router
))
847 if (op
->ifindex
!= path
->ifindex
)
854 void ospf_route_copy_nexthops(struct ospf_route
*to
, struct list
*from
)
856 struct listnode
*node
, *nnode
;
857 struct ospf_path
*path
;
861 for (ALL_LIST_ELEMENTS(from
, node
, nnode
, path
))
862 /* The same routes are just discarded. */
863 if (!ospf_path_lookup(to
->paths
, path
))
864 listnode_add(to
->paths
, ospf_path_dup(path
));
867 void ospf_route_subst_nexthops(struct ospf_route
*to
, struct list
*from
)
870 list_delete_all_node(to
->paths
);
871 ospf_route_copy_nexthops(to
, from
);
874 void ospf_route_subst(struct route_node
*rn
, struct ospf_route
*new_or
,
875 struct ospf_route
*over
)
878 ospf_route_free(rn
->info
);
880 ospf_route_copy_nexthops(new_or
, over
->paths
);
882 route_unlock_node(rn
);
885 void ospf_route_add(struct route_table
*rt
, struct prefix_ipv4
*p
,
886 struct ospf_route
*new_or
, struct ospf_route
*over
)
888 struct route_node
*rn
;
890 rn
= route_node_get(rt
, (struct prefix
*)p
);
892 ospf_route_copy_nexthops(new_or
, over
->paths
);
895 if (IS_DEBUG_OSPF_EVENT
)
896 zlog_debug("ospf_route_add(): something's wrong !");
897 route_unlock_node(rn
);
904 void ospf_prune_unreachable_networks(struct route_table
*rt
)
906 struct route_node
*rn
, *next
;
907 struct ospf_route
* or ;
909 if (IS_DEBUG_OSPF_EVENT
)
910 zlog_debug("Pruning unreachable networks");
912 for (rn
= route_top(rt
); rn
; rn
= next
) {
913 next
= route_next(rn
);
914 if (rn
->info
!= NULL
) {
916 if (listcount(or->paths
) == 0) {
917 if (IS_DEBUG_OSPF_EVENT
)
918 zlog_debug("Pruning route to %pFX",
923 route_unlock_node(rn
);
929 void ospf_prune_unreachable_routers(struct route_table
*rtrs
)
931 struct route_node
*rn
, *next
;
932 struct ospf_route
* or ;
933 struct listnode
*node
, *nnode
;
936 if (IS_DEBUG_OSPF_EVENT
)
937 zlog_debug("Pruning unreachable routers");
939 for (rn
= route_top(rtrs
); rn
; rn
= next
) {
940 next
= route_next(rn
);
941 if ((paths
= rn
->info
) == NULL
)
944 for (ALL_LIST_ELEMENTS(paths
, node
, nnode
, or)) {
945 if (listcount(or->paths
) == 0) {
946 if (IS_DEBUG_OSPF_EVENT
) {
947 zlog_debug("Pruning route to rtr %pI4",
954 listnode_delete(paths
, or);
959 if (listcount(paths
) == 0) {
960 if (IS_DEBUG_OSPF_EVENT
)
961 zlog_debug("Pruning router node %pI4",
966 route_unlock_node(rn
);
971 int ospf_add_discard_route(struct ospf
*ospf
, struct route_table
*rt
,
972 struct ospf_area
*area
, struct prefix_ipv4
*p
)
974 struct route_node
*rn
;
975 struct ospf_route
* or, *new_or
;
977 rn
= route_node_get(rt
, (struct prefix
*)p
);
980 if (IS_DEBUG_OSPF_EVENT
)
982 "ospf_add_discard_route(): router installation error");
986 if (rn
->info
) /* If the route to the same destination is found */
988 route_unlock_node(rn
);
992 if (or->path_type
== OSPF_PATH_INTRA_AREA
) {
993 if (IS_DEBUG_OSPF_EVENT
)
995 "ospf_add_discard_route(): an intra-area route exists");
999 if (or->type
== OSPF_DESTINATION_DISCARD
) {
1000 if (IS_DEBUG_OSPF_EVENT
)
1002 "ospf_add_discard_route(): discard entry already installed");
1006 ospf_route_free(rn
->info
);
1009 if (IS_DEBUG_OSPF_EVENT
)
1010 zlog_debug("ospf_add_discard_route(): adding %pFX", p
);
1012 new_or
= ospf_route_new();
1013 new_or
->type
= OSPF_DESTINATION_DISCARD
;
1014 new_or
->id
.s_addr
= INADDR_ANY
;
1016 new_or
->u
.std
.area_id
= area
->area_id
;
1017 new_or
->u
.std
.external_routing
= area
->external_routing
;
1018 new_or
->path_type
= OSPF_PATH_INTER_AREA
;
1021 ospf_zebra_add_discard(ospf
, p
);
1026 void ospf_delete_discard_route(struct ospf
*ospf
, struct route_table
*rt
,
1027 struct prefix_ipv4
*p
)
1029 struct route_node
*rn
;
1030 struct ospf_route
* or ;
1032 if (IS_DEBUG_OSPF_EVENT
)
1033 zlog_debug("ospf_delete_discard_route(): deleting %pFX", p
);
1035 rn
= route_node_lookup(rt
, (struct prefix
*)p
);
1038 if (IS_DEBUG_OSPF_EVENT
)
1040 "ospf_delete_discard_route(): no route found");
1046 if (or->path_type
== OSPF_PATH_INTRA_AREA
) {
1047 if (IS_DEBUG_OSPF_EVENT
)
1049 "ospf_delete_discard_route(): an intra-area route exists");
1053 if (or->type
!= OSPF_DESTINATION_DISCARD
) {
1054 if (IS_DEBUG_OSPF_EVENT
)
1056 "ospf_delete_discard_route(): not a discard entry");
1060 /* free the route entry and the route node */
1061 ospf_route_free(rn
->info
);
1064 route_unlock_node(rn
);
1065 route_unlock_node(rn
);
1067 /* remove the discard entry from the rib */
1068 ospf_zebra_delete_discard(ospf
, p
);