]>
git.proxmox.com Git - mirror_frr.git/blob - ospfd/ospf_ase.c
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 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
34 #include "ospfd/ospfd.h"
35 #include "ospfd/ospf_interface.h"
36 #include "ospfd/ospf_ism.h"
37 #include "ospfd/ospf_asbr.h"
38 #include "ospfd/ospf_lsa.h"
39 #include "ospfd/ospf_lsdb.h"
40 #include "ospfd/ospf_neighbor.h"
41 #include "ospfd/ospf_nsm.h"
42 #include "ospfd/ospf_spf.h"
43 #include "ospfd/ospf_route.h"
44 #include "ospfd/ospf_ase.h"
45 #include "ospfd/ospf_zebra.h"
46 #include "ospfd/ospf_dump.h"
49 ospf_find_asbr_route (struct ospf
*ospf
,
50 struct route_table
*rtrs
, struct prefix_ipv4
*asbr
)
52 struct route_node
*rn
;
53 struct ospf_route
*or, *best
= NULL
;
54 struct listnode
*node
;
61 rn
= route_node_lookup (rtrs
, (struct prefix
*) asbr
);
65 route_unlock_node (rn
);
69 /* First try to find intra-area non-bb paths. */
70 if (!CHECK_FLAG (ospf
->config
, OSPF_RFC1583_COMPATIBLE
))
71 for (ALL_LIST_ELEMENTS_RO ((struct list
*) rn
->info
, node
, or))
72 if (or->cost
< OSPF_LS_INFINITY
)
73 if (!OSPF_IS_AREA_ID_BACKBONE (or->u
.std
.area_id
) &&
74 or->path_type
== OSPF_PATH_INTRA_AREA
)
75 listnode_add (chosen
, or);
77 /* If none is found -- look through all. */
78 if (listcount (chosen
) == 0)
84 /* Now find the route with least cost. */
85 for (ALL_LIST_ELEMENTS_RO (chosen
, node
, or))
86 if (or->cost
< OSPF_LS_INFINITY
)
90 else if (best
->cost
> or->cost
)
92 else if (best
->cost
== or->cost
&&
93 IPV4_ADDR_CMP (&best
->u
.std
.area_id
,
94 &or->u
.std
.area_id
) < 0)
98 if (chosen
!= rn
->info
)
105 ospf_find_asbr_route_through_area (struct route_table
*rtrs
,
106 struct prefix_ipv4
*asbr
,
107 struct ospf_area
*area
)
109 struct route_node
*rn
;
115 rn
= route_node_lookup (rtrs
, (struct prefix
*) asbr
);
119 struct listnode
*node
;
120 struct ospf_route
*or;
122 route_unlock_node (rn
);
124 for (ALL_LIST_ELEMENTS_RO ((struct list
*) rn
->info
, node
, or))
125 if (IPV4_ADDR_SAME (&or->u
.std
.area_id
, &area
->area_id
))
133 ospf_ase_complete_direct_routes (struct ospf_route
*ro
, struct in_addr nexthop
)
135 struct listnode
*node
;
136 struct ospf_path
*op
;
138 for (ALL_LIST_ELEMENTS_RO (ro
->paths
, node
, op
))
139 if (op
->nexthop
.s_addr
== 0)
140 op
->nexthop
.s_addr
= nexthop
.s_addr
;
144 ospf_ase_forward_address_check (struct ospf
*ospf
, struct in_addr fwd_addr
)
146 struct listnode
*ifn
;
147 struct ospf_interface
*oi
;
149 for (ALL_LIST_ELEMENTS_RO (ospf
->oiflist
, ifn
, oi
))
150 if (if_is_operative (oi
->ifp
))
151 if (oi
->type
!= OSPF_IFTYPE_VIRTUALLINK
)
152 if (IPV4_ADDR_SAME (&oi
->address
->u
.prefix4
, &fwd_addr
))
159 /* Calculate ASBR route. */
160 static struct ospf_route
*
161 ospf_ase_calculate_asbr_route (struct ospf
*ospf
,
162 struct route_table
*rt_network
,
163 struct route_table
*rt_router
,
164 struct as_external_lsa
*al
)
166 struct prefix_ipv4 asbr
;
167 struct ospf_route
*asbr_route
;
168 struct route_node
*rn
;
170 /* Find ASBR route from Router routing table. */
171 asbr
.family
= AF_INET
;
172 asbr
.prefix
= al
->header
.adv_router
;
173 asbr
.prefixlen
= IPV4_MAX_BITLEN
;
174 apply_mask_ipv4 (&asbr
);
176 asbr_route
= ospf_find_asbr_route (ospf
, rt_router
, &asbr
);
178 if (asbr_route
== NULL
)
180 if (IS_DEBUG_OSPF (lsa
, LSA
))
181 zlog_debug ("ospf_ase_calculate(): Route to ASBR %s not found",
182 inet_ntoa (asbr
.prefix
));
186 if (!(asbr_route
->u
.std
.flags
& ROUTER_LSA_EXTERNAL
))
188 if (IS_DEBUG_OSPF (lsa
, LSA
))
189 zlog_debug ("ospf_ase_calculate(): Originating router is not an ASBR");
193 if (al
->e
[0].fwd_addr
.s_addr
!= 0)
195 if (IS_DEBUG_OSPF (lsa
, LSA
))
196 zlog_debug ("ospf_ase_calculate(): "
197 "Forwarding address is not 0.0.0.0.");
199 if (! ospf_ase_forward_address_check (ospf
, al
->e
[0].fwd_addr
))
201 if (IS_DEBUG_OSPF (lsa
, LSA
))
202 zlog_debug ("ospf_ase_calculate(): "
203 "Forwarding address is one of our addresses, Ignore.");
207 if (IS_DEBUG_OSPF (lsa
, LSA
))
208 zlog_debug ("ospf_ase_calculate(): "
209 "Looking up in the Network Routing Table.");
211 /* Looking up the path to the fwd_addr from Network route. */
212 asbr
.family
= AF_INET
;
213 asbr
.prefix
= al
->e
[0].fwd_addr
;
214 asbr
.prefixlen
= IPV4_MAX_BITLEN
;
216 rn
= route_node_match (rt_network
, (struct prefix
*) &asbr
);
220 if (IS_DEBUG_OSPF (lsa
, LSA
))
221 zlog_debug ("ospf_ase_calculate(): "
222 "Couldn't find a route to the forwarding address.");
226 route_unlock_node (rn
);
228 if ((asbr_route
= rn
->info
) == NULL
)
230 if (IS_DEBUG_OSPF (lsa
, LSA
))
231 zlog_debug ("ospf_ase_calculate(): "
232 "Somehow OSPF route to ASBR is lost");
241 static struct ospf_route
*
242 ospf_ase_calculate_new_route (struct ospf_lsa
*lsa
,
243 struct ospf_route
*asbr_route
, u_int32_t metric
)
245 struct as_external_lsa
*al
;
246 struct ospf_route
*new;
248 al
= (struct as_external_lsa
*) lsa
->data
;
250 new = ospf_route_new ();
252 /* Set redistributed type -- does make sense? */
253 /* new->type = type; */
254 new->id
= al
->header
.id
;
255 new->mask
= al
->mask
;
257 if (!IS_EXTERNAL_METRIC (al
->e
[0].tos
))
259 if (IS_DEBUG_OSPF (lsa
, LSA
))
260 zlog_debug ("Route[External]: type-1 created.");
261 new->path_type
= OSPF_PATH_TYPE1_EXTERNAL
;
262 new->cost
= asbr_route
->cost
+ metric
; /* X + Y */
266 if (IS_DEBUG_OSPF (lsa
, LSA
))
267 zlog_debug ("Route[External]: type-2 created.");
268 new->path_type
= OSPF_PATH_TYPE2_EXTERNAL
;
269 new->cost
= asbr_route
->cost
; /* X */
270 new->u
.ext
.type2_cost
= metric
; /* Y */
273 new->type
= OSPF_DESTINATION_NETWORK
;
274 new->u
.ext
.origin
= lsa
;
275 new->u
.ext
.tag
= ntohl (al
->e
[0].route_tag
);
276 new->u
.ext
.asbr
= asbr_route
;
278 assert (new != asbr_route
);
283 #define OSPF_ASE_CALC_INTERVAL 1
286 ospf_ase_calculate_route (struct ospf
*ospf
, struct ospf_lsa
* lsa
)
289 struct as_external_lsa
*al
;
290 struct ospf_route
*asbr_route
;
291 struct prefix_ipv4 asbr
, p
;
292 struct route_node
*rn
;
293 struct ospf_route
*new, *or;
297 al
= (struct as_external_lsa
*) lsa
->data
;
299 if (lsa
->data
->type
== OSPF_AS_NSSA_LSA
)
300 if (IS_DEBUG_OSPF_NSSA
)
301 zlog_debug ("ospf_ase_calc(): Processing Type-7");
303 /* Stay away from any Local Translated Type-7 LSAs */
304 if (CHECK_FLAG (lsa
->flags
, OSPF_LSA_LOCAL_XLT
))
306 if (IS_DEBUG_OSPF_NSSA
)
307 zlog_debug ("ospf_ase_calc(): Rejecting Local Xlt'd");
311 if (IS_DEBUG_OSPF (lsa
, LSA
))
312 zlog_debug ("Route[External]: Calculate AS-external-LSA to %s/%d",
313 inet_ntoa (al
->header
.id
), ip_masklen (al
->mask
));
314 /* (1) If the cost specified by the LSA is LSInfinity, or if the
315 LSA's LS age is equal to MaxAge, then examine the next LSA. */
316 if ((metric
= GET_METRIC (al
->e
[0].metric
)) >= OSPF_LS_INFINITY
)
318 if (IS_DEBUG_OSPF (lsa
, LSA
))
319 zlog_debug ("Route[External]: Metric is OSPF_LS_INFINITY");
322 if (IS_LSA_MAXAGE (lsa
))
324 if (IS_DEBUG_OSPF (lsa
, LSA
))
325 zlog_debug ("Route[External]: AS-external-LSA is MAXAGE");
329 /* (2) If the LSA was originated by the calculating router itself,
330 examine the next LSA. */
331 if (IS_LSA_SELF (lsa
))
333 if (IS_DEBUG_OSPF (lsa
, LSA
))
334 zlog_debug ("Route[External]: AS-external-LSA is self originated");
338 /* (3) Call the destination described by the LSA N. N's address is
339 obtained by masking the LSA's Link State ID with the
340 network/subnet mask contained in the body of the LSA. Look
341 up the routing table entries (potentially one per attached
342 area) for the AS boundary router (ASBR) that originated the
343 LSA. If no entries exist for router ASBR (i.e., ASBR is
344 unreachable), do nothing with this LSA and consider the next
347 asbr
.family
= AF_INET
;
348 asbr
.prefix
= al
->header
.adv_router
;
349 asbr
.prefixlen
= IPV4_MAX_BITLEN
;
350 apply_mask_ipv4 (&asbr
);
352 asbr_route
= ospf_find_asbr_route (ospf
, ospf
->new_rtrs
, &asbr
);
353 if (asbr_route
== NULL
)
355 if (IS_DEBUG_OSPF (lsa
, LSA
))
356 zlog_debug ("Route[External]: Can't find originating ASBR route");
359 if (!(asbr_route
->u
.std
.flags
& ROUTER_LSA_EXTERNAL
))
361 if (IS_DEBUG_OSPF (lsa
, LSA
))
362 zlog_debug ("Route[External]: Originating router is not an ASBR");
366 /* Else, this LSA describes an AS external path to destination
367 N. Examine the forwarding address specified in the AS-
368 external-LSA. This indicates the IP address to which
369 packets for the destination should be forwarded. */
371 if (al
->e
[0].fwd_addr
.s_addr
== 0)
373 /* If the forwarding address is set to 0.0.0.0, packets should
374 be sent to the ASBR itself. Among the multiple routing table
375 entries for the ASBR, select the preferred entry as follows.
376 If RFC1583Compatibility is set to "disabled", prune the set
377 of routing table entries for the ASBR as described in
378 Section 16.4.1. In any case, among the remaining routing
379 table entries, select the routing table entry with the least
380 cost; when there are multiple least cost routing table
381 entries the entry whose associated area has the largest OSPF
382 Area ID (when considered as an unsigned 32-bit integer) is
385 /* asbr_route already contains the requested route */
389 /* If the forwarding address is non-zero, look up the
390 forwarding address in the routing table.[24] The matching
391 routing table entry must specify an intra-area or inter-area
392 path; if no such path exists, do nothing with the LSA and
393 consider the next in the list. */
394 if (! ospf_ase_forward_address_check (ospf
, al
->e
[0].fwd_addr
))
396 if (IS_DEBUG_OSPF (lsa
, LSA
))
397 zlog_debug ("Route[External]: Forwarding address is our router "
402 asbr
.family
= AF_INET
;
403 asbr
.prefix
= al
->e
[0].fwd_addr
;
404 asbr
.prefixlen
= IPV4_MAX_BITLEN
;
406 rn
= route_node_match (ospf
->new_table
, (struct prefix
*) &asbr
);
408 if (rn
== NULL
|| (asbr_route
= rn
->info
) == NULL
)
410 if (IS_DEBUG_OSPF (lsa
, LSA
))
411 zlog_debug ("Route[External]: Can't find route to forwarding "
414 route_unlock_node (rn
);
418 route_unlock_node (rn
);
421 /* (4) Let X be the cost specified by the preferred routing table
422 entry for the ASBR/forwarding address, and Y the cost
423 specified in the LSA. X is in terms of the link state
424 metric, and Y is a type 1 or 2 external metric. */
427 /* (5) Look up the routing table entry for the destination N. If
428 no entry exists for N, install the AS external path to N,
429 with next hop equal to the list of next hops to the
430 forwarding address, and advertising router equal to ASBR.
431 If the external metric type is 1, then the path-type is set
432 to type 1 external and the cost is equal to X+Y. If the
433 external metric type is 2, the path-type is set to type 2
434 external, the link state component of the route's cost is X,
435 and the type 2 cost is Y. */
436 new = ospf_ase_calculate_new_route (lsa
, asbr_route
, metric
);
438 /* (6) Compare the AS external path described by the LSA with the
439 existing paths in N's routing table entry, as follows. If
440 the new path is preferred, it replaces the present paths in
441 N's routing table entry. If the new path is of equal
442 preference, it is added to N's routing table entry's list of
447 p
.prefix
= al
->header
.id
;
448 p
.prefixlen
= ip_masklen (al
->mask
);
450 /* if there is a Intra/Inter area route to the N
451 do not install external route */
452 if ((rn
= route_node_lookup (ospf
->new_table
,
453 (struct prefix
*) &p
)))
455 route_unlock_node(rn
);
456 if (rn
->info
== NULL
)
457 zlog_info ("Route[External]: rn->info NULL");
459 ospf_route_free (new);
462 /* Find a route to the same dest */
463 /* If there is no route, create new one. */
464 if ((rn
= route_node_lookup (ospf
->new_external_route
,
465 (struct prefix
*) &p
)))
466 route_unlock_node(rn
);
468 if (!rn
|| (or = rn
->info
) == NULL
)
470 if (IS_DEBUG_OSPF (lsa
, LSA
))
471 zlog_debug ("Route[External]: Adding a new route %s/%d",
472 inet_ntoa (p
.prefix
), p
.prefixlen
);
474 ospf_route_add (ospf
->new_external_route
, &p
, new, asbr_route
);
476 if (al
->e
[0].fwd_addr
.s_addr
)
477 ospf_ase_complete_direct_routes (new, al
->e
[0].fwd_addr
);
482 /* (a) Intra-area and inter-area paths are always preferred
483 over AS external paths.
485 (b) Type 1 external paths are always preferred over type 2
486 external paths. When all paths are type 2 external
487 paths, the paths with the smallest advertised type 2
488 metric are always preferred. */
489 ret
= ospf_route_cmp (ospf
, new, or);
491 /* (c) If the new AS external path is still indistinguishable
492 from the current paths in the N's routing table entry,
493 and RFC1583Compatibility is set to "disabled", select
494 the preferred paths based on the intra-AS paths to the
495 ASBR/forwarding addresses, as specified in Section
498 (d) If the new AS external path is still indistinguishable
499 from the current paths in the N's routing table entry,
500 select the preferred path based on a least cost
501 comparison. Type 1 external paths are compared by
502 looking at the sum of the distance to the forwarding
503 address and the advertised type 1 metric (X+Y). Type 2
504 external paths advertising equal type 2 metrics are
505 compared by looking at the distance to the forwarding
508 /* New route is better */
511 if (IS_DEBUG_OSPF (lsa
, LSA
))
512 zlog_debug ("Route[External]: New route is better");
513 ospf_route_subst (rn
, new, asbr_route
);
514 if (al
->e
[0].fwd_addr
.s_addr
)
515 ospf_ase_complete_direct_routes (new, al
->e
[0].fwd_addr
);
519 /* Old route is better */
522 if (IS_DEBUG_OSPF (lsa
, LSA
))
523 zlog_debug ("Route[External]: Old route is better");
526 /* Routes are equal */
529 if (IS_DEBUG_OSPF (lsa
, LSA
))
530 zlog_debug ("Route[External]: Routes are equal");
531 ospf_route_copy_nexthops (or, asbr_route
->paths
);
532 if (al
->e
[0].fwd_addr
.s_addr
)
533 ospf_ase_complete_direct_routes (or, al
->e
[0].fwd_addr
);
536 /* Make sure setting newly calculated ASBR route.*/
537 or->u
.ext
.asbr
= asbr_route
;
539 ospf_route_free (new);
546 ospf_ase_route_match_same (struct route_table
*rt
, struct prefix
*prefix
,
547 struct ospf_route
*newor
)
549 struct route_node
*rn
;
550 struct ospf_route
*or;
551 struct ospf_path
*op
;
552 struct ospf_path
*newop
;
556 if (! rt
|| ! prefix
)
559 rn
= route_node_lookup (rt
, prefix
);
563 route_unlock_node (rn
);
566 if (or->path_type
!= newor
->path_type
)
569 switch (or->path_type
)
571 case OSPF_PATH_TYPE1_EXTERNAL
:
572 if (or->cost
!= newor
->cost
)
575 case OSPF_PATH_TYPE2_EXTERNAL
:
576 if ((or->cost
!= newor
->cost
) ||
577 (or->u
.ext
.type2_cost
!= newor
->u
.ext
.type2_cost
))
585 if (or->paths
->count
!= newor
->paths
->count
)
588 /* Check each path. */
589 for (n1
= listhead (or->paths
), n2
= listhead (newor
->paths
);
590 n1
&& n2
; n1
= listnextnode (n1
), n2
= listnextnode (n2
))
592 op
= listgetdata (n1
);
593 newop
= listgetdata (n2
);
595 if (! IPV4_ADDR_SAME (&op
->nexthop
, &newop
->nexthop
))
597 if (op
->ifindex
!= newop
->ifindex
)
601 if (or->u
.ext
.tag
!= newor
->u
.ext
.tag
)
608 ospf_ase_compare_tables (struct route_table
*new_external_route
,
609 struct route_table
*old_external_route
)
611 struct route_node
*rn
, *new_rn
;
612 struct ospf_route
*or;
614 /* Remove deleted routes */
615 for (rn
= route_top (old_external_route
); rn
; rn
= route_next (rn
))
618 if (! (new_rn
= route_node_lookup (new_external_route
, &rn
->p
)))
619 ospf_zebra_delete ((struct prefix_ipv4
*) &rn
->p
, or);
621 route_unlock_node (new_rn
);
625 /* Install new routes */
626 for (rn
= route_top (new_external_route
); rn
; rn
= route_next (rn
))
627 if ((or = rn
->info
) != NULL
)
628 if (! ospf_ase_route_match_same (old_external_route
, &rn
->p
, or))
629 ospf_zebra_add ((struct prefix_ipv4
*) &rn
->p
, or);
635 ospf_ase_calculate_timer (struct thread
*t
)
638 struct ospf_lsa
*lsa
;
639 struct route_node
*rn
;
640 struct listnode
*node
;
641 struct ospf_area
*area
;
642 struct timeval start_time
, stop_time
;
644 ospf
= THREAD_ARG (t
);
645 ospf
->t_ase_calc
= NULL
;
651 monotime(&start_time
);
653 /* Calculate external route for each AS-external-LSA */
654 LSDB_LOOP (EXTERNAL_LSDB (ospf
), rn
, lsa
)
655 ospf_ase_calculate_route (ospf
, lsa
);
657 /* This version simple adds to the table all NSSA areas */
659 for (ALL_LIST_ELEMENTS_RO (ospf
->areas
, node
, area
))
661 if (IS_DEBUG_OSPF_NSSA
)
662 zlog_debug ("ospf_ase_calculate_timer(): looking at area %s",
663 inet_ntoa (area
->area_id
));
665 if (area
->external_routing
== OSPF_AREA_NSSA
)
666 LSDB_LOOP (NSSA_LSDB (area
), rn
, lsa
)
667 ospf_ase_calculate_route (ospf
, lsa
);
669 /* kevinm: And add the NSSA routes in ospf_top */
670 LSDB_LOOP (NSSA_LSDB (ospf
),rn
,lsa
)
671 ospf_ase_calculate_route(ospf
,lsa
);
673 /* Compare old and new external routing table and install the
674 difference info zebra/kernel */
675 ospf_ase_compare_tables (ospf
->new_external_route
,
676 ospf
->old_external_route
);
678 /* Delete old external routing table */
679 ospf_route_table_free (ospf
->old_external_route
);
680 ospf
->old_external_route
= ospf
->new_external_route
;
681 ospf
->new_external_route
= route_table_init ();
683 monotime(&stop_time
);
685 zlog_info ("SPF Processing Time(usecs): External Routes: %lld\n",
686 (stop_time
.tv_sec
- start_time
.tv_sec
)*1000000LL+
687 (stop_time
.tv_usec
- start_time
.tv_usec
));
693 ospf_ase_calculate_schedule (struct ospf
*ospf
)
702 ospf_ase_calculate_timer_add (struct ospf
*ospf
)
707 thread_add_timer(master
, ospf_ase_calculate_timer
, ospf
,
708 OSPF_ASE_CALC_INTERVAL
, &ospf
->t_ase_calc
);
712 ospf_ase_register_external_lsa (struct ospf_lsa
*lsa
, struct ospf
*top
)
714 struct route_node
*rn
;
715 struct prefix_ipv4 p
;
717 struct as_external_lsa
*al
;
719 al
= (struct as_external_lsa
*) lsa
->data
;
721 p
.prefix
= lsa
->data
->id
;
722 p
.prefixlen
= ip_masklen (al
->mask
);
723 apply_mask_ipv4 (&p
);
725 rn
= route_node_get (top
->external_lsas
, (struct prefix
*) &p
);
726 if ((lst
= rn
->info
) == NULL
)
727 rn
->info
= lst
= list_new();
729 route_unlock_node (rn
);
731 /* We assume that if LSA is deleted from DB
732 is is also deleted from this RT */
733 listnode_add (lst
, ospf_lsa_lock (lsa
)); /* external_lsas lst */
737 ospf_ase_unregister_external_lsa (struct ospf_lsa
*lsa
, struct ospf
*top
)
739 struct route_node
*rn
;
740 struct prefix_ipv4 p
;
742 struct as_external_lsa
*al
;
744 al
= (struct as_external_lsa
*) lsa
->data
;
746 p
.prefix
= lsa
->data
->id
;
747 p
.prefixlen
= ip_masklen (al
->mask
);
748 apply_mask_ipv4 (&p
);
750 rn
= route_node_lookup (top
->external_lsas
, (struct prefix
*) &p
);
754 listnode_delete (lst
, lsa
);
755 ospf_lsa_unlock (&lsa
); /* external_lsas list */
756 route_unlock_node (rn
);
761 ospf_ase_external_lsas_finish (struct route_table
*rt
)
763 struct route_node
*rn
;
764 struct ospf_lsa
*lsa
;
766 struct listnode
*node
, *nnode
;
768 for (rn
= route_top (rt
); rn
; rn
= route_next (rn
))
769 if ((lst
= rn
->info
) != NULL
)
771 for (ALL_LIST_ELEMENTS (lst
, node
, nnode
, lsa
))
772 ospf_lsa_unlock (&lsa
); /* external_lsas lst */
776 route_table_finish (rt
);
780 ospf_ase_incremental_update (struct ospf
*ospf
, struct ospf_lsa
*lsa
)
783 struct listnode
*node
;
784 struct route_node
*rn
, *rn2
;
785 struct prefix_ipv4 p
;
786 struct route_table
*tmp_old
;
787 struct as_external_lsa
*al
;
789 al
= (struct as_external_lsa
*) lsa
->data
;
791 p
.prefix
= lsa
->data
->id
;
792 p
.prefixlen
= ip_masklen (al
->mask
);
793 apply_mask_ipv4 (&p
);
795 /* if new_table is NULL, there was no spf calculation, thus
796 incremental update is unneeded */
797 if (!ospf
->new_table
)
800 /* If there is already an intra-area or inter-area route
801 to the destination, no recalculation is necessary
802 (internal routes take precedence). */
804 rn
= route_node_lookup (ospf
->new_table
, (struct prefix
*) &p
);
807 route_unlock_node (rn
);
812 rn
= route_node_lookup (ospf
->external_lsas
, (struct prefix
*) &p
);
816 route_unlock_node (rn
);
818 for (ALL_LIST_ELEMENTS_RO (lsas
, node
, lsa
))
819 ospf_ase_calculate_route (ospf
, lsa
);
821 /* prepare temporary old routing table for compare */
822 tmp_old
= route_table_init ();
823 rn
= route_node_lookup (ospf
->old_external_route
, (struct prefix
*) &p
);
826 rn2
= route_node_get (tmp_old
, (struct prefix
*) &p
);
827 rn2
->info
= rn
->info
;
828 route_unlock_node (rn
);
831 /* install changes to zebra */
832 ospf_ase_compare_tables (ospf
->new_external_route
, tmp_old
);
834 /* update ospf->old_external_route table */
836 ospf_route_free ((struct ospf_route
*) rn
->info
);
838 rn2
= route_node_lookup (ospf
->new_external_route
, (struct prefix
*) &p
);
839 /* if new route exists, install it to ospf->old_external_route */
840 if (rn2
&& rn2
->info
)
843 rn
= route_node_get (ospf
->old_external_route
, (struct prefix
*) &p
);
844 rn
->info
= rn2
->info
;
848 /* remove route node from ospf->old_external_route */
852 route_unlock_node (rn
);
858 /* rn2->info is stored in route node of ospf->old_external_route */
860 route_unlock_node (rn2
);
861 route_unlock_node (rn2
);
864 route_table_finish (tmp_old
);