]>
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
) {
214 if (or->type
== OSPF_DESTINATION_NETWORK
) {
215 if (or->paths
->count
!= newor
->paths
->count
)
218 /* Check each path. */
219 for (n1
= listhead(or->paths
),
220 n2
= listhead(newor
->paths
);
221 n1
&& n2
; n1
= listnextnode_unchecked(n1
),
222 n2
= listnextnode_unchecked(n2
)) {
223 op
= listgetdata(n1
);
224 newop
= listgetdata(n2
);
226 if (!IPV4_ADDR_SAME(&op
->nexthop
,
229 if (op
->ifindex
!= newop
->ifindex
)
232 /* check TI-LFA backup paths */
233 if (!ospf_route_backup_path_same(&op
->srni
,
238 } else if (prefix_same(&rn
->p
, (struct prefix
*)prefix
))
244 /* delete routes generated from AS-External routes if there is a inter/intra
247 static void ospf_route_delete_same_ext(struct ospf
*ospf
,
248 struct route_table
*external_routes
,
249 struct route_table
*routes
)
251 struct route_node
*rn
, *ext_rn
;
253 if ((external_routes
== NULL
) || (routes
== NULL
))
256 /* Remove deleted routes */
257 for (rn
= route_top(routes
); rn
; rn
= route_next(rn
)) {
258 if (rn
&& rn
->info
) {
259 struct prefix_ipv4
*p
= (struct prefix_ipv4
*)(&rn
->p
);
260 if ((ext_rn
= route_node_lookup(external_routes
,
261 (struct prefix
*)p
))) {
263 ospf_zebra_delete(ospf
, p
,
265 ospf_route_free(ext_rn
->info
);
268 route_unlock_node(ext_rn
);
274 /* rt: Old, cmprt: New */
275 static void ospf_route_delete_uniq(struct ospf
*ospf
, struct route_table
*rt
,
276 struct route_table
*cmprt
)
278 struct route_node
*rn
;
279 struct ospf_route
* or ;
281 for (rn
= route_top(rt
); rn
; rn
= route_next(rn
))
282 if ((or = rn
->info
) != NULL
)
283 if (or->path_type
== OSPF_PATH_INTRA_AREA
||
284 or->path_type
== OSPF_PATH_INTER_AREA
) {
285 if (or->type
== OSPF_DESTINATION_NETWORK
) {
286 if (!ospf_route_exist_new_table(
288 (struct prefix_ipv4
*)&rn
295 } else if (or->type
== OSPF_DESTINATION_DISCARD
)
296 if (!ospf_route_exist_new_table(
298 (struct prefix_ipv4
*)&rn
300 ospf_zebra_delete_discard(
307 /* Install routes to table. */
308 void ospf_route_install(struct ospf
*ospf
, struct route_table
*rt
)
310 struct route_node
*rn
;
311 struct ospf_route
* or ;
313 /* rt contains new routing table, new_table contains an old one.
316 ospf_route_table_free(ospf
->old_table
);
318 ospf
->old_table
= ospf
->new_table
;
319 ospf
->new_table
= rt
;
321 /* Delete old routes. */
323 ospf_route_delete_uniq(ospf
, ospf
->old_table
, rt
);
324 if (ospf
->old_external_route
)
325 ospf_route_delete_same_ext(ospf
, ospf
->old_external_route
, rt
);
327 /* Install new routes. */
328 for (rn
= route_top(rt
); rn
; rn
= route_next(rn
))
329 if ((or = rn
->info
) != NULL
) {
330 if (or->type
== OSPF_DESTINATION_NETWORK
) {
331 if (!ospf_route_match_same(
333 (struct prefix_ipv4
*)&rn
->p
, or))
336 (struct prefix_ipv4
*)&rn
->p
,
338 } else if (or->type
== OSPF_DESTINATION_DISCARD
)
339 if (!ospf_route_match_same(
341 (struct prefix_ipv4
*)&rn
->p
, or))
342 ospf_zebra_add_discard(
344 (struct prefix_ipv4
*)&rn
->p
);
348 /* RFC2328 16.1. (4). For "router". */
349 void ospf_intra_add_router(struct route_table
*rt
, struct vertex
*v
,
350 struct ospf_area
*area
)
352 struct route_node
*rn
;
353 struct ospf_route
* or ;
354 struct prefix_ipv4 p
;
355 struct router_lsa
*lsa
;
357 if (IS_DEBUG_OSPF_EVENT
)
358 zlog_debug("ospf_intra_add_router: Start");
360 lsa
= (struct router_lsa
*)v
->lsa
;
362 if (IS_DEBUG_OSPF_EVENT
)
363 zlog_debug("ospf_intra_add_router: LS ID: %pI4",
366 if (!OSPF_IS_AREA_BACKBONE(area
))
367 ospf_vl_up_check(area
, lsa
->header
.id
, v
);
369 if (!CHECK_FLAG(lsa
->flags
, ROUTER_LSA_SHORTCUT
))
370 area
->shortcut_capability
= 0;
372 /* If the newly added vertex is an area border router or AS boundary
373 router, a routing table entry is added whose destination type is
375 if (!IS_ROUTER_LSA_BORDER(lsa
) && !IS_ROUTER_LSA_EXTERNAL(lsa
)) {
376 if (IS_DEBUG_OSPF_EVENT
)
378 "ospf_intra_add_router: this router is neither ASBR nor ABR, skipping it");
382 /* Update ABR and ASBR count in this area. */
383 if (IS_ROUTER_LSA_BORDER(lsa
))
385 if (IS_ROUTER_LSA_EXTERNAL(lsa
))
388 /* The Options field found in the associated router-LSA is copied
389 into the routing table entry's Optional capabilities field. Call
390 the newly added vertex Router X. */
391 or = ospf_route_new();
394 or->u
.std
.area_id
= area
->area_id
;
395 or->u
.std
.external_routing
= area
->external_routing
;
396 or->path_type
= OSPF_PATH_INTRA_AREA
;
397 or->cost
= v
->distance
;
398 or->type
= OSPF_DESTINATION_ROUTER
;
399 or->u
.std
.origin
= (struct lsa_header
*)lsa
;
400 or->u
.std
.options
= lsa
->header
.options
;
401 or->u
.std
.flags
= lsa
->flags
;
403 /* If Router X is the endpoint of one of the calculating router's
404 virtual links, and the virtual link uses Area A as Transit area:
405 the virtual link is declared up, the IP address of the virtual
406 interface is set to the IP address of the outgoing interface
407 calculated above for Router X, and the virtual neighbor's IP
408 address is set to Router X's interface address (contained in
409 Router X's router-LSA) that points back to the root of the
410 shortest- path tree; equivalently, this is the interface that
411 points back to Router X's parent vertex on the shortest-path tree
412 (similar to the calculation in Section 16.1.1). */
416 p
.prefixlen
= IPV4_MAX_BITLEN
;
419 if (IS_DEBUG_OSPF_EVENT
)
420 zlog_debug("ospf_intra_add_router: talking about %pFX", &p
);
422 rn
= route_node_get(rt
, (struct prefix
*)&p
);
424 /* Note that we keep all routes to ABRs and ASBRs, not only the best */
425 if (rn
->info
== NULL
)
426 rn
->info
= list_new();
428 route_unlock_node(rn
);
430 ospf_route_copy_nexthops_from_vertex(area
, or, v
);
432 listnode_add(rn
->info
, or);
434 if (IS_DEBUG_OSPF_EVENT
)
435 zlog_debug("ospf_intra_add_router: Stop");
438 /* RFC2328 16.1. (4). For transit network. */
439 void ospf_intra_add_transit(struct route_table
*rt
, struct vertex
*v
,
440 struct ospf_area
*area
)
442 struct route_node
*rn
;
443 struct ospf_route
* or ;
444 struct prefix_ipv4 p
;
445 struct network_lsa
*lsa
;
447 lsa
= (struct network_lsa
*)v
->lsa
;
449 /* If the newly added vertex is a transit network, the routing table
450 entry for the network is located. The entry's Destination ID is
451 the IP network number, which can be obtained by masking the
452 Vertex ID (Link State ID) with its associated subnet mask (found
453 in the body of the associated network-LSA). */
456 p
.prefixlen
= ip_masklen(lsa
->mask
);
459 rn
= route_node_get(rt
, (struct prefix
*)&p
);
461 /* If the routing table entry already exists (i.e., there is already
462 an intra-area route to the destination installed in the routing
463 table), multiple vertices have mapped to the same IP network.
464 For example, this can occur when a new Designated Router is being
465 established. In this case, the current routing table entry
466 should be overwritten if and only if the newly found path is just
467 as short and the current routing table entry's Link State Origin
468 has a smaller Link State ID than the newly added vertex' LSA. */
470 struct ospf_route
*cur_or
;
472 route_unlock_node(rn
);
475 if (v
->distance
> cur_or
->cost
476 || IPV4_ADDR_CMP(&cur_or
->u
.std
.origin
->id
, &lsa
->header
.id
)
480 ospf_route_free(rn
->info
);
483 or = ospf_route_new();
486 or->u
.std
.area_id
= area
->area_id
;
487 or->u
.std
.external_routing
= area
->external_routing
;
488 or->path_type
= OSPF_PATH_INTRA_AREA
;
489 or->cost
= v
->distance
;
490 or->type
= OSPF_DESTINATION_NETWORK
;
491 or->u
.std
.origin
= (struct lsa_header
*)lsa
;
493 ospf_route_copy_nexthops_from_vertex(area
, or, v
);
498 /* RFC2328 16.1. second stage. */
499 void ospf_intra_add_stub(struct route_table
*rt
, struct router_lsa_link
*link
,
500 struct vertex
*v
, struct ospf_area
*area
,
501 int parent_is_root
, int lsa_pos
)
504 struct route_node
*rn
;
505 struct ospf_route
* or ;
506 struct prefix_ipv4 p
;
507 struct router_lsa
*lsa
;
508 struct ospf_interface
*oi
= NULL
;
509 struct ospf_path
*path
;
511 if (IS_DEBUG_OSPF_EVENT
)
512 zlog_debug("ospf_intra_add_stub(): Start");
514 lsa
= (struct router_lsa
*)v
->lsa
;
517 p
.prefix
= link
->link_id
;
518 p
.prefixlen
= ip_masklen(link
->link_data
);
521 if (IS_DEBUG_OSPF_EVENT
)
522 zlog_debug("ospf_intra_add_stub(): processing route to %pFX",
525 /* (1) Calculate the distance D of stub network from the root. D is
526 equal to the distance from the root to the router vertex
527 (calculated in stage 1), plus the stub network link's advertised
529 cost
= v
->distance
+ ntohs(link
->m
[0].metric
);
531 if (IS_DEBUG_OSPF_EVENT
)
533 "ospf_intra_add_stub(): calculated cost is %d + %d = %d",
534 v
->distance
, ntohs(link
->m
[0].metric
), cost
);
536 /* PtP links with /32 masks adds host routes to remote, directly
537 * connected hosts, see RFC 2328, 12.4.1.1, Option 1.
538 * Such routes can just be ignored for the sake of tidyness.
540 if (parent_is_root
&& link
->link_data
.s_addr
== 0xffffffff
541 && ospf_if_lookup_by_local_addr(area
->ospf
, NULL
, link
->link_id
)) {
542 if (IS_DEBUG_OSPF_EVENT
)
543 zlog_debug("%s: ignoring host route %pI4/32 to self.",
544 __func__
, &link
->link_id
);
548 rn
= route_node_get(rt
, (struct prefix
*)&p
);
550 /* Lookup current routing table. */
552 struct ospf_route
*cur_or
;
554 route_unlock_node(rn
);
558 if (IS_DEBUG_OSPF_EVENT
)
560 "ospf_intra_add_stub(): another route to the same prefix found with cost %u",
563 /* Compare this distance to the current best cost to the stub
564 network. This is done by looking up the stub network's
565 current routing table entry. If the calculated distance D is
566 larger, go on to examine the next stub network link in the
568 if (cost
> cur_or
->cost
) {
569 if (IS_DEBUG_OSPF_EVENT
)
571 "ospf_intra_add_stub(): old route is better, exit");
575 /* (2) If this step is reached, the stub network's routing table
576 entry must be updated. Calculate the set of next hops that
577 would result from using the stub network link. This
578 calculation is shown in Section 16.1.1; input to this
579 calculation is the destination (the stub network) and the
580 parent vertex (the router vertex). If the distance D is the
581 same as the current routing table cost, simply add this set
582 of next hops to the routing table entry's list of next hops.
583 In this case, the routing table already has a Link State
584 Origin. If this Link State Origin is a router-LSA whose Link
585 State ID is smaller than V's Router ID, reset the Link State
586 Origin to V's router-LSA. */
588 if (cost
== cur_or
->cost
) {
589 if (IS_DEBUG_OSPF_EVENT
)
591 "ospf_intra_add_stub(): routes are equal, merge");
593 ospf_route_copy_nexthops_from_vertex(area
, cur_or
, v
);
595 if (IPV4_ADDR_CMP(&cur_or
->u
.std
.origin
->id
,
598 cur_or
->u
.std
.origin
= (struct lsa_header
*)lsa
;
602 /* Otherwise D is smaller than the routing table cost.
603 Overwrite the current routing table entry by setting the
604 routing table entry's cost to D, and by setting the entry's
605 list of next hops to the newly calculated set. Set the
606 routing table entry's Link State Origin to V's router-LSA.
607 Then go on to examine the next stub network link. */
609 if (cost
< cur_or
->cost
) {
610 if (IS_DEBUG_OSPF_EVENT
)
612 "ospf_intra_add_stub(): new route is better, set it");
616 list_delete_all_node(cur_or
->paths
);
618 ospf_route_copy_nexthops_from_vertex(area
, cur_or
, v
);
620 cur_or
->u
.std
.origin
= (struct lsa_header
*)lsa
;
625 if (IS_DEBUG_OSPF_EVENT
)
626 zlog_debug("ospf_intra_add_stub(): installing new route");
628 or = ospf_route_new();
631 or->u
.std
.area_id
= area
->area_id
;
632 or->u
.std
.external_routing
= area
->external_routing
;
633 or->path_type
= OSPF_PATH_INTRA_AREA
;
635 or->type
= OSPF_DESTINATION_NETWORK
;
636 or->u
.std
.origin
= (struct lsa_header
*)lsa
;
638 /* Nexthop is depend on connection type. */
639 if (v
!= area
->spf
) {
640 if (IS_DEBUG_OSPF_EVENT
)
642 "ospf_intra_add_stub(): this network is on remote router");
643 ospf_route_copy_nexthops_from_vertex(area
, or, v
);
645 if (IS_DEBUG_OSPF_EVENT
)
647 "ospf_intra_add_stub(): this network is on this router");
650 * Only deal with interface data when we
653 if (!area
->spf_dry_run
)
654 oi
= ospf_if_lookup_by_lsa_pos(area
, lsa_pos
);
656 if (oi
|| area
->spf_dry_run
) {
657 if (IS_DEBUG_OSPF_EVENT
)
659 "ospf_intra_add_stub(): the lsa pos is %d",
662 path
= ospf_path_new();
663 path
->nexthop
.s_addr
= INADDR_ANY
;
666 path
->ifindex
= oi
->ifp
->ifindex
;
667 if (CHECK_FLAG(oi
->connected
->flags
,
668 ZEBRA_IFA_UNNUMBERED
))
669 path
->unnumbered
= 1;
672 listnode_add(or->paths
, path
);
674 if (IS_DEBUG_OSPF_EVENT
)
676 "ospf_intra_add_stub(): where's the interface ?");
682 if (IS_DEBUG_OSPF_EVENT
)
683 zlog_debug("ospf_intra_add_stub(): Stop");
686 static const char *const ospf_path_type_str
[] = {
687 "unknown-type", "intra-area", "inter-area", "type1-external",
691 void ospf_route_table_dump(struct route_table
*rt
)
693 struct route_node
*rn
;
694 struct ospf_route
* or ;
695 struct listnode
*pnode
;
696 struct ospf_path
*path
;
698 zlog_debug("========== OSPF routing table ==========");
699 for (rn
= route_top(rt
); rn
; rn
= route_next(rn
))
700 if ((or = rn
->info
) != NULL
) {
701 if (or->type
== OSPF_DESTINATION_NETWORK
) {
702 zlog_debug("N %-18pFX %-15pI4 %s %d", &rn
->p
,
704 ospf_path_type_str
[or->path_type
],
706 for (ALL_LIST_ELEMENTS_RO(or->paths
, pnode
,
708 zlog_debug(" -> %pI4",
711 zlog_debug("R %-18pI4 %-15pI4 %s %d",
714 ospf_path_type_str
[or->path_type
],
717 zlog_debug("========================================");
720 /* This is 16.4.1 implementation.
721 o Intra-area paths using non-backbone areas are always the most preferred.
722 o The other paths, intra-area backbone paths and inter-area paths,
723 are of equal preference. */
724 static int ospf_asbr_route_cmp(struct ospf
*ospf
, struct ospf_route
*r1
,
725 struct ospf_route
*r2
)
727 uint8_t r1_type
, r2_type
;
729 r1_type
= r1
->path_type
;
730 r2_type
= r2
->path_type
;
732 /* r1/r2 itself is backbone, and it's Inter-area path. */
733 if (OSPF_IS_AREA_ID_BACKBONE(r1
->u
.std
.area_id
))
734 r1_type
= OSPF_PATH_INTER_AREA
;
735 if (OSPF_IS_AREA_ID_BACKBONE(r2
->u
.std
.area_id
))
736 r2_type
= OSPF_PATH_INTER_AREA
;
738 return (r1_type
- r2_type
);
741 /* Compare two routes.
742 ret < 0 -- r1 is better.
743 ret == 0 -- r1 and r2 are the same.
744 ret > 0 -- r2 is better. */
745 int ospf_route_cmp(struct ospf
*ospf
, struct ospf_route
*r1
,
746 struct ospf_route
*r2
)
750 /* Path types of r1 and r2 are not the same. */
751 if ((ret
= (r1
->path_type
- r2
->path_type
)))
754 if (IS_DEBUG_OSPF_EVENT
)
755 zlog_debug("Route[Compare]: Path types are the same.");
756 /* Path types are the same, compare any cost. */
757 switch (r1
->path_type
) {
758 case OSPF_PATH_INTRA_AREA
:
759 case OSPF_PATH_INTER_AREA
:
761 case OSPF_PATH_TYPE1_EXTERNAL
:
762 if (!CHECK_FLAG(ospf
->config
, OSPF_RFC1583_COMPATIBLE
)) {
763 ret
= ospf_asbr_route_cmp(ospf
, r1
->u
.ext
.asbr
,
769 case OSPF_PATH_TYPE2_EXTERNAL
:
770 if ((ret
= (r1
->u
.ext
.type2_cost
- r2
->u
.ext
.type2_cost
)))
773 if (!CHECK_FLAG(ospf
->config
, OSPF_RFC1583_COMPATIBLE
)) {
774 ret
= ospf_asbr_route_cmp(ospf
, r1
->u
.ext
.asbr
,
782 /* Anyway, compare the costs. */
783 return (r1
->cost
- r2
->cost
);
786 static int ospf_path_exist(struct list
*plist
, struct in_addr nexthop
,
787 struct ospf_interface
*oi
)
789 struct listnode
*node
, *nnode
;
790 struct ospf_path
*path
;
792 for (ALL_LIST_ELEMENTS(plist
, node
, nnode
, path
))
793 if (IPV4_ADDR_SAME(&path
->nexthop
, &nexthop
)
794 && path
->ifindex
== oi
->ifp
->ifindex
)
800 void ospf_route_copy_nexthops_from_vertex(struct ospf_area
*area
,
801 struct ospf_route
*to
,
804 struct listnode
*node
;
805 struct ospf_path
*path
;
806 struct vertex_nexthop
*nexthop
;
807 struct vertex_parent
*vp
;
808 struct ospf_interface
*oi
= NULL
;
812 for (ALL_LIST_ELEMENTS_RO(v
->parents
, node
, vp
)) {
813 nexthop
= vp
->nexthop
;
816 * Only deal with interface data when we
819 if (!area
->spf_dry_run
)
820 oi
= ospf_if_lookup_by_lsa_pos(area
, nexthop
->lsa_pos
);
822 if ((oi
&& !ospf_path_exist(to
->paths
, nexthop
->router
, oi
))
823 || area
->spf_dry_run
) {
824 path
= ospf_path_new();
825 path
->nexthop
= nexthop
->router
;
826 path
->adv_router
= v
->id
;
829 path
->ifindex
= oi
->ifp
->ifindex
;
830 if (CHECK_FLAG(oi
->connected
->flags
,
831 ZEBRA_IFA_UNNUMBERED
))
832 path
->unnumbered
= 1;
835 listnode_add(to
->paths
, path
);
840 struct ospf_path
*ospf_path_lookup(struct list
*plist
, struct ospf_path
*path
)
842 struct listnode
*node
;
843 struct ospf_path
*op
;
845 for (ALL_LIST_ELEMENTS_RO(plist
, node
, op
)) {
846 if (!IPV4_ADDR_SAME(&op
->nexthop
, &path
->nexthop
))
848 if (!IPV4_ADDR_SAME(&op
->adv_router
, &path
->adv_router
))
850 if (op
->ifindex
!= path
->ifindex
)
857 void ospf_route_copy_nexthops(struct ospf_route
*to
, struct list
*from
)
859 struct listnode
*node
, *nnode
;
860 struct ospf_path
*path
;
864 for (ALL_LIST_ELEMENTS(from
, node
, nnode
, path
))
865 /* The same routes are just discarded. */
866 if (!ospf_path_lookup(to
->paths
, path
))
867 listnode_add(to
->paths
, ospf_path_dup(path
));
870 void ospf_route_subst_nexthops(struct ospf_route
*to
, struct list
*from
)
873 list_delete_all_node(to
->paths
);
874 ospf_route_copy_nexthops(to
, from
);
877 void ospf_route_subst(struct route_node
*rn
, struct ospf_route
*new_or
,
878 struct ospf_route
*over
)
881 ospf_route_free(rn
->info
);
883 ospf_route_copy_nexthops(new_or
, over
->paths
);
885 route_unlock_node(rn
);
888 void ospf_route_add(struct route_table
*rt
, struct prefix_ipv4
*p
,
889 struct ospf_route
*new_or
, struct ospf_route
*over
)
891 struct route_node
*rn
;
893 rn
= route_node_get(rt
, (struct prefix
*)p
);
895 ospf_route_copy_nexthops(new_or
, over
->paths
);
898 if (IS_DEBUG_OSPF_EVENT
)
899 zlog_debug("ospf_route_add(): something's wrong !");
900 route_unlock_node(rn
);
907 void ospf_prune_unreachable_networks(struct route_table
*rt
)
909 struct route_node
*rn
, *next
;
910 struct ospf_route
* or ;
912 if (IS_DEBUG_OSPF_EVENT
)
913 zlog_debug("Pruning unreachable networks");
915 for (rn
= route_top(rt
); rn
; rn
= next
) {
916 next
= route_next(rn
);
917 if (rn
->info
!= NULL
) {
919 if (listcount(or->paths
) == 0) {
920 if (IS_DEBUG_OSPF_EVENT
)
921 zlog_debug("Pruning route to %pFX",
926 route_unlock_node(rn
);
932 void ospf_prune_unreachable_routers(struct route_table
*rtrs
)
934 struct route_node
*rn
, *next
;
935 struct ospf_route
* or ;
936 struct listnode
*node
, *nnode
;
939 if (IS_DEBUG_OSPF_EVENT
)
940 zlog_debug("Pruning unreachable routers");
942 for (rn
= route_top(rtrs
); rn
; rn
= next
) {
943 next
= route_next(rn
);
944 if ((paths
= rn
->info
) == NULL
)
947 for (ALL_LIST_ELEMENTS(paths
, node
, nnode
, or)) {
948 if (listcount(or->paths
) == 0) {
949 if (IS_DEBUG_OSPF_EVENT
) {
950 zlog_debug("Pruning route to rtr %pI4",
957 listnode_delete(paths
, or);
962 if (listcount(paths
) == 0) {
963 if (IS_DEBUG_OSPF_EVENT
)
964 zlog_debug("Pruning router node %pI4",
969 route_unlock_node(rn
);
974 int ospf_add_discard_route(struct ospf
*ospf
, struct route_table
*rt
,
975 struct ospf_area
*area
, struct prefix_ipv4
*p
)
977 struct route_node
*rn
;
978 struct ospf_route
* or, *new_or
;
980 rn
= route_node_get(rt
, (struct prefix
*)p
);
983 if (IS_DEBUG_OSPF_EVENT
)
985 "ospf_add_discard_route(): router installation error");
989 if (rn
->info
) /* If the route to the same destination is found */
991 route_unlock_node(rn
);
995 if (or->path_type
== OSPF_PATH_INTRA_AREA
) {
996 if (IS_DEBUG_OSPF_EVENT
)
998 "ospf_add_discard_route(): an intra-area route exists");
1002 if (or->type
== OSPF_DESTINATION_DISCARD
) {
1003 if (IS_DEBUG_OSPF_EVENT
)
1005 "ospf_add_discard_route(): discard entry already installed");
1009 ospf_route_free(rn
->info
);
1012 if (IS_DEBUG_OSPF_EVENT
)
1013 zlog_debug("ospf_add_discard_route(): adding %pFX", p
);
1015 new_or
= ospf_route_new();
1016 new_or
->type
= OSPF_DESTINATION_DISCARD
;
1017 new_or
->id
.s_addr
= INADDR_ANY
;
1019 new_or
->u
.std
.area_id
= area
->area_id
;
1020 new_or
->u
.std
.external_routing
= area
->external_routing
;
1021 new_or
->path_type
= OSPF_PATH_INTER_AREA
;
1024 ospf_zebra_add_discard(ospf
, p
);
1029 void ospf_delete_discard_route(struct ospf
*ospf
, struct route_table
*rt
,
1030 struct prefix_ipv4
*p
)
1032 struct route_node
*rn
;
1033 struct ospf_route
* or ;
1035 if (IS_DEBUG_OSPF_EVENT
)
1036 zlog_debug("ospf_delete_discard_route(): deleting %pFX", p
);
1038 rn
= route_node_lookup(rt
, (struct prefix
*)p
);
1041 if (IS_DEBUG_OSPF_EVENT
)
1043 "ospf_delete_discard_route(): no route found");
1049 if (or->path_type
== OSPF_PATH_INTRA_AREA
) {
1050 if (IS_DEBUG_OSPF_EVENT
)
1052 "ospf_delete_discard_route(): an intra-area route exists");
1056 if (or->type
!= OSPF_DESTINATION_DISCARD
) {
1057 if (IS_DEBUG_OSPF_EVENT
)
1059 "ospf_delete_discard_route(): not a discard entry");
1063 /* free the route entry and the route node */
1064 ospf_route_free(rn
->info
);
1067 route_unlock_node(rn
);
1068 route_unlock_node(rn
);
1070 /* remove the discard entry from the rib */
1071 ospf_zebra_delete_discard(ospf
, p
);