2 * OSPF AS external route calculation.
3 * Copyright (C) 1999, 2000 Alex Zinin, 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
35 #include "ospfd/ospfd.h"
36 #include "ospfd/ospf_interface.h"
37 #include "ospfd/ospf_ism.h"
38 #include "ospfd/ospf_asbr.h"
39 #include "ospfd/ospf_lsa.h"
40 #include "ospfd/ospf_lsdb.h"
41 #include "ospfd/ospf_neighbor.h"
42 #include "ospfd/ospf_nsm.h"
43 #include "ospfd/ospf_spf.h"
44 #include "ospfd/ospf_route.h"
45 #include "ospfd/ospf_ase.h"
46 #include "ospfd/ospf_zebra.h"
47 #include "ospfd/ospf_dump.h"
50 ospf_find_asbr_route (struct ospf
*ospf
,
51 struct route_table
*rtrs
, struct prefix_ipv4
*asbr
)
53 struct route_node
*rn
;
54 struct ospf_route
*or, *best
= NULL
;
55 struct listnode
*node
;
62 rn
= route_node_lookup (rtrs
, (struct prefix
*) asbr
);
66 route_unlock_node (rn
);
70 /* First try to find intra-area non-bb paths. */
71 if (!CHECK_FLAG (ospf
->config
, OSPF_RFC1583_COMPATIBLE
))
72 for (ALL_LIST_ELEMENTS_RO ((struct list
*) rn
->info
, node
, or))
73 if (or->cost
< OSPF_LS_INFINITY
)
74 if (!OSPF_IS_AREA_ID_BACKBONE (or->u
.std
.area_id
) &&
75 or->path_type
== OSPF_PATH_INTRA_AREA
)
76 listnode_add (chosen
, or);
78 /* If none is found -- look through all. */
79 if (listcount (chosen
) == 0)
85 /* Now find the route with least cost. */
86 for (ALL_LIST_ELEMENTS_RO (chosen
, node
, or))
87 if (or->cost
< OSPF_LS_INFINITY
)
91 else if (best
->cost
> or->cost
)
93 else if (best
->cost
== or->cost
&&
94 IPV4_ADDR_CMP (&best
->u
.std
.area_id
,
95 &or->u
.std
.area_id
) < 0)
99 if (chosen
!= rn
->info
)
100 list_delete (chosen
);
106 ospf_find_asbr_route_through_area (struct route_table
*rtrs
,
107 struct prefix_ipv4
*asbr
,
108 struct ospf_area
*area
)
110 struct route_node
*rn
;
116 rn
= route_node_lookup (rtrs
, (struct prefix
*) asbr
);
120 struct listnode
*node
;
121 struct ospf_route
*or;
123 route_unlock_node (rn
);
125 for (ALL_LIST_ELEMENTS_RO ((struct list
*) rn
->info
, node
, or))
126 if (IPV4_ADDR_SAME (&or->u
.std
.area_id
, &area
->area_id
))
134 ospf_ase_complete_direct_routes (struct ospf_route
*ro
, struct in_addr nexthop
)
136 struct listnode
*node
;
137 struct ospf_path
*op
;
138 struct interface
*ifp
;
140 for (ALL_LIST_ELEMENTS_RO (ro
->paths
, node
, op
))
141 if (op
->nexthop
.s_addr
== 0)
142 op
->nexthop
.s_addr
= nexthop
.s_addr
;
146 ospf_ase_forward_address_check (struct ospf
*ospf
, struct in_addr fwd_addr
)
148 struct listnode
*ifn
;
149 struct ospf_interface
*oi
;
151 for (ALL_LIST_ELEMENTS_RO (ospf
->oiflist
, ifn
, oi
))
152 if (if_is_operative (oi
->ifp
))
153 if (oi
->type
!= OSPF_IFTYPE_VIRTUALLINK
)
154 if (IPV4_ADDR_SAME (&oi
->address
->u
.prefix4
, &fwd_addr
))
161 /* Calculate ASBR route. */
162 static struct ospf_route
*
163 ospf_ase_calculate_asbr_route (struct ospf
*ospf
,
164 struct route_table
*rt_network
,
165 struct route_table
*rt_router
,
166 struct as_external_lsa
*al
)
168 struct prefix_ipv4 asbr
;
169 struct ospf_route
*asbr_route
;
170 struct route_node
*rn
;
172 /* Find ASBR route from Router routing table. */
173 asbr
.family
= AF_INET
;
174 asbr
.prefix
= al
->header
.adv_router
;
175 asbr
.prefixlen
= IPV4_MAX_BITLEN
;
176 apply_mask_ipv4 (&asbr
);
178 asbr_route
= ospf_find_asbr_route (ospf
, rt_router
, &asbr
);
180 if (asbr_route
== NULL
)
182 if (IS_DEBUG_OSPF (lsa
, LSA
))
183 zlog_debug ("ospf_ase_calculate(): Route to ASBR %s not found",
184 inet_ntoa (asbr
.prefix
));
188 if (!(asbr_route
->u
.std
.flags
& ROUTER_LSA_EXTERNAL
))
190 if (IS_DEBUG_OSPF (lsa
, LSA
))
191 zlog_debug ("ospf_ase_calculate(): Originating router is not an ASBR");
195 if (al
->e
[0].fwd_addr
.s_addr
!= 0)
197 if (IS_DEBUG_OSPF (lsa
, LSA
))
198 zlog_debug ("ospf_ase_calculate(): "
199 "Forwarding address is not 0.0.0.0.");
201 if (! ospf_ase_forward_address_check (ospf
, al
->e
[0].fwd_addr
))
203 if (IS_DEBUG_OSPF (lsa
, LSA
))
204 zlog_debug ("ospf_ase_calculate(): "
205 "Forwarding address is one of our addresses, Ignore.");
209 if (IS_DEBUG_OSPF (lsa
, LSA
))
210 zlog_debug ("ospf_ase_calculate(): "
211 "Looking up in the Network Routing Table.");
213 /* Looking up the path to the fwd_addr from Network route. */
214 asbr
.family
= AF_INET
;
215 asbr
.prefix
= al
->e
[0].fwd_addr
;
216 asbr
.prefixlen
= IPV4_MAX_BITLEN
;
218 rn
= route_node_match (rt_network
, (struct prefix
*) &asbr
);
222 if (IS_DEBUG_OSPF (lsa
, LSA
))
223 zlog_debug ("ospf_ase_calculate(): "
224 "Couldn't find a route to the forwarding address.");
228 route_unlock_node (rn
);
230 if ((asbr_route
= rn
->info
) == NULL
)
232 if (IS_DEBUG_OSPF (lsa
, LSA
))
233 zlog_debug ("ospf_ase_calculate(): "
234 "Somehow OSPF route to ASBR is lost");
243 static struct ospf_route
*
244 ospf_ase_calculate_new_route (struct ospf_lsa
*lsa
,
245 struct ospf_route
*asbr_route
, u_int32_t metric
)
247 struct as_external_lsa
*al
;
248 struct ospf_route
*new;
250 al
= (struct as_external_lsa
*) lsa
->data
;
252 new = ospf_route_new ();
254 /* Set redistributed type -- does make sense? */
255 /* new->type = type; */
256 new->id
= al
->header
.id
;
257 new->mask
= al
->mask
;
259 if (!IS_EXTERNAL_METRIC (al
->e
[0].tos
))
261 if (IS_DEBUG_OSPF (lsa
, LSA
))
262 zlog_debug ("Route[External]: type-1 created.");
263 new->path_type
= OSPF_PATH_TYPE1_EXTERNAL
;
264 new->cost
= asbr_route
->cost
+ metric
; /* X + Y */
268 if (IS_DEBUG_OSPF (lsa
, LSA
))
269 zlog_debug ("Route[External]: type-2 created.");
270 new->path_type
= OSPF_PATH_TYPE2_EXTERNAL
;
271 new->cost
= asbr_route
->cost
; /* X */
272 new->u
.ext
.type2_cost
= metric
; /* Y */
275 new->type
= OSPF_DESTINATION_NETWORK
;
276 new->u
.ext
.origin
= lsa
;
277 new->u
.ext
.tag
= ntohl (al
->e
[0].route_tag
);
278 new->u
.ext
.asbr
= asbr_route
;
280 assert (new != asbr_route
);
285 #define OSPF_ASE_CALC_INTERVAL 1
288 ospf_ase_calculate_route (struct ospf
*ospf
, struct ospf_lsa
* lsa
)
291 struct as_external_lsa
*al
;
292 struct ospf_route
*asbr_route
;
293 struct prefix_ipv4 asbr
, p
;
294 struct route_node
*rn
;
295 struct ospf_route
*new, *or;
299 al
= (struct as_external_lsa
*) lsa
->data
;
301 if (lsa
->data
->type
== OSPF_AS_NSSA_LSA
)
302 if (IS_DEBUG_OSPF_NSSA
)
303 zlog_debug ("ospf_ase_calc(): Processing Type-7");
305 /* Stay away from any Local Translated Type-7 LSAs */
306 if (CHECK_FLAG (lsa
->flags
, OSPF_LSA_LOCAL_XLT
))
308 if (IS_DEBUG_OSPF_NSSA
)
309 zlog_debug ("ospf_ase_calc(): Rejecting Local Xlt'd");
313 if (IS_DEBUG_OSPF (lsa
, LSA
))
314 zlog_debug ("Route[External]: Calculate AS-external-LSA to %s/%d",
315 inet_ntoa (al
->header
.id
), ip_masklen (al
->mask
));
316 /* (1) If the cost specified by the LSA is LSInfinity, or if the
317 LSA's LS age is equal to MaxAge, then examine the next LSA. */
318 if ((metric
= GET_METRIC (al
->e
[0].metric
)) >= OSPF_LS_INFINITY
)
320 if (IS_DEBUG_OSPF (lsa
, LSA
))
321 zlog_debug ("Route[External]: Metric is OSPF_LS_INFINITY");
324 if (IS_LSA_MAXAGE (lsa
))
326 if (IS_DEBUG_OSPF (lsa
, LSA
))
327 zlog_debug ("Route[External]: AS-external-LSA is MAXAGE");
331 /* (2) If the LSA was originated by the calculating router itself,
332 examine the next LSA. */
333 if (IS_LSA_SELF (lsa
))
335 if (IS_DEBUG_OSPF (lsa
, LSA
))
336 zlog_debug ("Route[External]: AS-external-LSA is self originated");
340 /* (3) Call the destination described by the LSA N. N's address is
341 obtained by masking the LSA's Link State ID with the
342 network/subnet mask contained in the body of the LSA. Look
343 up the routing table entries (potentially one per attached
344 area) for the AS boundary router (ASBR) that originated the
345 LSA. If no entries exist for router ASBR (i.e., ASBR is
346 unreachable), do nothing with this LSA and consider the next
349 asbr
.family
= AF_INET
;
350 asbr
.prefix
= al
->header
.adv_router
;
351 asbr
.prefixlen
= IPV4_MAX_BITLEN
;
352 apply_mask_ipv4 (&asbr
);
354 asbr_route
= ospf_find_asbr_route (ospf
, ospf
->new_rtrs
, &asbr
);
355 if (asbr_route
== NULL
)
357 if (IS_DEBUG_OSPF (lsa
, LSA
))
358 zlog_debug ("Route[External]: Can't find originating ASBR route");
361 if (!(asbr_route
->u
.std
.flags
& ROUTER_LSA_EXTERNAL
))
363 if (IS_DEBUG_OSPF (lsa
, LSA
))
364 zlog_debug ("Route[External]: Originating router is not an ASBR");
368 /* Else, this LSA describes an AS external path to destination
369 N. Examine the forwarding address specified in the AS-
370 external-LSA. This indicates the IP address to which
371 packets for the destination should be forwarded. */
373 if (al
->e
[0].fwd_addr
.s_addr
== 0)
375 /* If the forwarding address is set to 0.0.0.0, packets should
376 be sent to the ASBR itself. Among the multiple routing table
377 entries for the ASBR, select the preferred entry as follows.
378 If RFC1583Compatibility is set to "disabled", prune the set
379 of routing table entries for the ASBR as described in
380 Section 16.4.1. In any case, among the remaining routing
381 table entries, select the routing table entry with the least
382 cost; when there are multiple least cost routing table
383 entries the entry whose associated area has the largest OSPF
384 Area ID (when considered as an unsigned 32-bit integer) is
387 /* asbr_route already contains the requested route */
391 /* If the forwarding address is non-zero, look up the
392 forwarding address in the routing table.[24] The matching
393 routing table entry must specify an intra-area or inter-area
394 path; if no such path exists, do nothing with the LSA and
395 consider the next in the list. */
396 if (! ospf_ase_forward_address_check (ospf
, al
->e
[0].fwd_addr
))
398 if (IS_DEBUG_OSPF (lsa
, LSA
))
399 zlog_debug ("Route[External]: Forwarding address is our router "
404 asbr
.family
= AF_INET
;
405 asbr
.prefix
= al
->e
[0].fwd_addr
;
406 asbr
.prefixlen
= IPV4_MAX_BITLEN
;
408 rn
= route_node_match (ospf
->new_table
, (struct prefix
*) &asbr
);
410 if (rn
== NULL
|| (asbr_route
= rn
->info
) == NULL
)
412 if (IS_DEBUG_OSPF (lsa
, LSA
))
413 zlog_debug ("Route[External]: Can't find route to forwarding "
416 route_unlock_node (rn
);
420 route_unlock_node (rn
);
423 /* (4) Let X be the cost specified by the preferred routing table
424 entry for the ASBR/forwarding address, and Y the cost
425 specified in the LSA. X is in terms of the link state
426 metric, and Y is a type 1 or 2 external metric. */
429 /* (5) Look up the routing table entry for the destination N. If
430 no entry exists for N, install the AS external path to N,
431 with next hop equal to the list of next hops to the
432 forwarding address, and advertising router equal to ASBR.
433 If the external metric type is 1, then the path-type is set
434 to type 1 external and the cost is equal to X+Y. If the
435 external metric type is 2, the path-type is set to type 2
436 external, the link state component of the route's cost is X,
437 and the type 2 cost is Y. */
438 new = ospf_ase_calculate_new_route (lsa
, asbr_route
, metric
);
440 /* (6) Compare the AS external path described by the LSA with the
441 existing paths in N's routing table entry, as follows. If
442 the new path is preferred, it replaces the present paths in
443 N's routing table entry. If the new path is of equal
444 preference, it is added to N's routing table entry's list of
449 p
.prefix
= al
->header
.id
;
450 p
.prefixlen
= ip_masklen (al
->mask
);
452 /* if there is a Intra/Inter area route to the N
453 do not install external route */
454 if (rn
= route_node_lookup (ospf
->new_table
,
455 (struct prefix
*) &p
))
457 route_unlock_node(rn
);
458 if (rn
->info
== NULL
)
459 zlog_info ("Route[External]: rn->info NULL");
461 ospf_route_free (new);
464 /* Find a route to the same dest */
465 /* If there is no route, create new one. */
466 if (rn
= route_node_lookup (ospf
->new_external_route
,
467 (struct prefix
*) &p
))
468 route_unlock_node(rn
);
470 if (!rn
|| (or = rn
->info
) == NULL
)
472 if (IS_DEBUG_OSPF (lsa
, LSA
))
473 zlog_debug ("Route[External]: Adding a new route %s/%d",
474 inet_ntoa (p
.prefix
), p
.prefixlen
);
476 ospf_route_add (ospf
->new_external_route
, &p
, new, asbr_route
);
478 if (al
->e
[0].fwd_addr
.s_addr
)
479 ospf_ase_complete_direct_routes (new, al
->e
[0].fwd_addr
);
484 /* (a) Intra-area and inter-area paths are always preferred
485 over AS external paths.
487 (b) Type 1 external paths are always preferred over type 2
488 external paths. When all paths are type 2 external
489 paths, the paths with the smallest advertised type 2
490 metric are always preferred. */
491 ret
= ospf_route_cmp (ospf
, new, or);
493 /* (c) If the new AS external path is still indistinguishable
494 from the current paths in the N's routing table entry,
495 and RFC1583Compatibility is set to "disabled", select
496 the preferred paths based on the intra-AS paths to the
497 ASBR/forwarding addresses, as specified in Section
500 (d) If the new AS external path is still indistinguishable
501 from the current paths in the N's routing table entry,
502 select the preferred path based on a least cost
503 comparison. Type 1 external paths are compared by
504 looking at the sum of the distance to the forwarding
505 address and the advertised type 1 metric (X+Y). Type 2
506 external paths advertising equal type 2 metrics are
507 compared by looking at the distance to the forwarding
510 /* New route is better */
513 if (IS_DEBUG_OSPF (lsa
, LSA
))
514 zlog_debug ("Route[External]: New route is better");
515 ospf_route_subst (rn
, new, asbr_route
);
516 if (al
->e
[0].fwd_addr
.s_addr
)
517 ospf_ase_complete_direct_routes (new, al
->e
[0].fwd_addr
);
521 /* Old route is better */
524 if (IS_DEBUG_OSPF (lsa
, LSA
))
525 zlog_debug ("Route[External]: Old route is better");
528 /* Routes are equal */
531 if (IS_DEBUG_OSPF (lsa
, LSA
))
532 zlog_debug ("Route[External]: Routes are equal");
533 ospf_route_copy_nexthops (or, asbr_route
->paths
);
534 if (al
->e
[0].fwd_addr
.s_addr
)
535 ospf_ase_complete_direct_routes (or, al
->e
[0].fwd_addr
);
538 /* Make sure setting newly calculated ASBR route.*/
539 or->u
.ext
.asbr
= asbr_route
;
541 ospf_route_free (new);
548 ospf_ase_route_match_same (struct route_table
*rt
, struct prefix
*prefix
,
549 struct ospf_route
*newor
)
551 struct route_node
*rn
;
552 struct ospf_route
*or;
553 struct ospf_path
*op
;
554 struct ospf_path
*newop
;
558 if (! rt
|| ! prefix
)
561 rn
= route_node_lookup (rt
, prefix
);
565 route_unlock_node (rn
);
568 if (or->path_type
!= newor
->path_type
)
571 switch (or->path_type
)
573 case OSPF_PATH_TYPE1_EXTERNAL
:
574 if (or->cost
!= newor
->cost
)
577 case OSPF_PATH_TYPE2_EXTERNAL
:
578 if ((or->cost
!= newor
->cost
) ||
579 (or->u
.ext
.type2_cost
!= newor
->u
.ext
.type2_cost
))
587 if (or->paths
->count
!= newor
->paths
->count
)
590 /* Check each path. */
591 for (n1
= listhead (or->paths
), n2
= listhead (newor
->paths
);
592 n1
&& n2
; n1
= listnextnode (n1
), n2
= listnextnode (n2
))
594 op
= listgetdata (n1
);
595 newop
= listgetdata (n2
);
597 if (! IPV4_ADDR_SAME (&op
->nexthop
, &newop
->nexthop
))
599 if (op
->ifindex
!= newop
->ifindex
)
606 ospf_ase_compare_tables (struct route_table
*new_external_route
,
607 struct route_table
*old_external_route
)
609 struct route_node
*rn
, *new_rn
;
610 struct ospf_route
*or;
612 /* Remove deleted routes */
613 for (rn
= route_top (old_external_route
); rn
; rn
= route_next (rn
))
616 if (! (new_rn
= route_node_lookup (new_external_route
, &rn
->p
)))
617 ospf_zebra_delete ((struct prefix_ipv4
*) &rn
->p
, or);
619 route_unlock_node (new_rn
);
623 /* Install new routes */
624 for (rn
= route_top (new_external_route
); rn
; rn
= route_next (rn
))
625 if ((or = rn
->info
) != NULL
)
626 if (! ospf_ase_route_match_same (old_external_route
, &rn
->p
, or))
627 ospf_zebra_add ((struct prefix_ipv4
*) &rn
->p
, or);
633 ospf_ase_calculate_timer (struct thread
*t
)
636 struct ospf_lsa
*lsa
;
637 struct route_node
*rn
;
638 struct listnode
*node
;
639 struct ospf_area
*area
;
641 ospf
= THREAD_ARG (t
);
642 ospf
->t_ase_calc
= NULL
;
648 /* Calculate external route for each AS-external-LSA */
649 LSDB_LOOP (EXTERNAL_LSDB (ospf
), rn
, lsa
)
650 ospf_ase_calculate_route (ospf
, lsa
);
652 /* This version simple adds to the table all NSSA areas */
654 for (ALL_LIST_ELEMENTS_RO (ospf
->areas
, node
, area
))
656 if (IS_DEBUG_OSPF_NSSA
)
657 zlog_debug ("ospf_ase_calculate_timer(): looking at area %s",
658 inet_ntoa (area
->area_id
));
660 if (area
->external_routing
== OSPF_AREA_NSSA
)
661 LSDB_LOOP (NSSA_LSDB (area
), rn
, lsa
)
662 ospf_ase_calculate_route (ospf
, lsa
);
664 /* kevinm: And add the NSSA routes in ospf_top */
665 LSDB_LOOP (NSSA_LSDB (ospf
),rn
,lsa
)
666 ospf_ase_calculate_route(ospf
,lsa
);
668 /* Compare old and new external routing table and install the
669 difference info zebra/kernel */
670 ospf_ase_compare_tables (ospf
->new_external_route
,
671 ospf
->old_external_route
);
673 /* Delete old external routing table */
674 ospf_route_table_free (ospf
->old_external_route
);
675 ospf
->old_external_route
= ospf
->new_external_route
;
676 ospf
->new_external_route
= route_table_init ();
682 ospf_ase_calculate_schedule (struct ospf
*ospf
)
691 ospf_ase_calculate_timer_add (struct ospf
*ospf
)
696 if (! ospf
->t_ase_calc
)
697 ospf
->t_ase_calc
= thread_add_timer (master
, ospf_ase_calculate_timer
,
698 ospf
, OSPF_ASE_CALC_INTERVAL
);
702 ospf_ase_register_external_lsa (struct ospf_lsa
*lsa
, struct ospf
*top
)
704 struct route_node
*rn
;
705 struct prefix_ipv4 p
;
707 struct as_external_lsa
*al
;
709 al
= (struct as_external_lsa
*) lsa
->data
;
711 p
.prefix
= lsa
->data
->id
;
712 p
.prefixlen
= ip_masklen (al
->mask
);
713 apply_mask_ipv4 (&p
);
715 rn
= route_node_get (top
->external_lsas
, (struct prefix
*) &p
);
716 if ((lst
= rn
->info
) == NULL
)
717 rn
->info
= lst
= list_new();
719 /* We assume that if LSA is deleted from DB
720 is is also deleted from this RT */
722 listnode_add (lst
, ospf_lsa_lock (lsa
)); /* external_lsas lst */
726 ospf_ase_unregister_external_lsa (struct ospf_lsa
*lsa
, struct ospf
*top
)
728 struct route_node
*rn
;
729 struct prefix_ipv4 p
;
731 struct as_external_lsa
*al
;
733 al
= (struct as_external_lsa
*) lsa
->data
;
735 p
.prefix
= lsa
->data
->id
;
736 p
.prefixlen
= ip_masklen (al
->mask
);
737 apply_mask_ipv4 (&p
);
739 rn
= route_node_get (top
->external_lsas
, (struct prefix
*) &p
);
742 /* XXX lst can be NULL */
744 listnode_delete (lst
, lsa
);
745 ospf_lsa_unlock (&lsa
); /* external_lsas list */
750 ospf_ase_external_lsas_finish (struct route_table
*rt
)
752 struct route_node
*rn
;
753 struct ospf_lsa
*lsa
;
755 struct listnode
*node
, *nnode
;
757 for (rn
= route_top (rt
); rn
; rn
= route_next (rn
))
758 if ((lst
= rn
->info
) != NULL
)
760 for (ALL_LIST_ELEMENTS (lst
, node
, nnode
, lsa
))
761 ospf_lsa_unlock (&lsa
); /* external_lsas lst */
765 route_table_finish (rt
);
769 ospf_ase_incremental_update (struct ospf
*ospf
, struct ospf_lsa
*lsa
)
772 struct listnode
*node
;
773 struct route_node
*rn
, *rn2
;
774 struct prefix_ipv4 p
;
775 struct route_table
*tmp_old
;
776 struct as_external_lsa
*al
;
778 al
= (struct as_external_lsa
*) lsa
->data
;
780 p
.prefix
= lsa
->data
->id
;
781 p
.prefixlen
= ip_masklen (al
->mask
);
782 apply_mask_ipv4 (&p
);
784 /* if new_table is NULL, there was no spf calculation, thus
785 incremental update is unneeded */
786 if (!ospf
->new_table
)
789 /* If there is already an intra-area or inter-area route
790 to the destination, no recalculation is necessary
791 (internal routes take precedence). */
793 rn
= route_node_lookup (ospf
->new_table
, (struct prefix
*) &p
);
796 route_unlock_node (rn
);
801 rn
= route_node_lookup (ospf
->external_lsas
, (struct prefix
*) &p
);
802 assert (rn
&& rn
->info
);
804 route_unlock_node (rn
);
806 for (ALL_LIST_ELEMENTS_RO (lsas
, node
, lsa
))
807 ospf_ase_calculate_route (ospf
, lsa
);
809 /* prepare temporary old routing table for compare */
810 tmp_old
= route_table_init ();
811 rn
= route_node_lookup (ospf
->old_external_route
, (struct prefix
*) &p
);
814 rn2
= route_node_get (tmp_old
, (struct prefix
*) &p
);
815 rn2
->info
= rn
->info
;
818 /* install changes to zebra */
819 ospf_ase_compare_tables (ospf
->new_external_route
, tmp_old
);
821 /* update ospf->old_external_route table */
823 ospf_route_free ((struct ospf_route
*) rn
->info
);
825 rn2
= route_node_lookup (ospf
->new_external_route
, (struct prefix
*) &p
);
826 /* if new route exists, install it to ospf->old_external_route */
827 if (rn2
&& rn2
->info
)
830 rn
= route_node_get (ospf
->old_external_route
, (struct prefix
*) &p
);
831 rn
->info
= rn2
->info
;
835 /* remove route node from ospf->old_external_route */
839 route_unlock_node (rn
);
840 route_unlock_node (rn
);
846 /* rn2->info is stored in route node of ospf->old_external_route */
848 route_unlock_node (rn2
);
849 route_unlock_node (rn2
);
852 route_table_finish (tmp_old
);