]> git.proxmox.com Git - mirror_frr.git/blame - ospfd/ospf_ase.c
* lib/prefix.[hc]: inet6_ntoa utility function copied from
[mirror_frr.git] / ospfd / ospf_ase.c
CommitLineData
718e3744 1/*
2 * OSPF AS external route calculation.
3 * Copyright (C) 1999, 2000 Alex Zinin, Toshiaki Takada
4 *
5 * This file is part of GNU Zebra.
6 *
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
10 * later version.
11 *
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.
16 *
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
20 * 02111-1307, USA.
21 */
22
23#include <zebra.h>
24
25#include "thread.h"
26#include "memory.h"
27#include "hash.h"
28#include "linklist.h"
29#include "prefix.h"
30#include "if.h"
31#include "table.h"
32#include "vty.h"
33#include "log.h"
34
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"
48
49#define DEBUG
50
51struct ospf_route *
68980084 52ospf_find_asbr_route (struct ospf *ospf,
53 struct route_table *rtrs, struct prefix_ipv4 *asbr)
718e3744 54{
55 struct route_node *rn;
56 struct ospf_route *or, *best = NULL;
52dc7ee6 57 struct listnode *node;
58 struct list *chosen;
718e3744 59
60 /* Sanity check. */
61 if (rtrs == NULL)
62 return NULL;
63
64 rn = route_node_lookup (rtrs, (struct prefix *) asbr);
65 if (! rn)
66 return NULL;
67
68 route_unlock_node (rn);
69
70 chosen = list_new ();
71
72 /* First try to find intra-area non-bb paths. */
68980084 73 if (!CHECK_FLAG (ospf->config, OSPF_RFC1583_COMPATIBLE))
52dc7ee6 74 for (node = listhead ((struct list *) rn->info); node; nextnode (node))
718e3744 75 if ((or = getdata (node)) != NULL)
76 if (or->cost < OSPF_LS_INFINITY)
77 if (!OSPF_IS_AREA_ID_BACKBONE (or->u.std.area_id) &&
78 or->path_type == OSPF_PATH_INTRA_AREA)
79 listnode_add (chosen, or);
80
81 /* If none is found -- look through all. */
82 if (listcount (chosen) == 0)
83 {
84 list_free (chosen);
85 chosen = rn->info;
86 }
87
88 /* Now find the route with least cost. */
89 for (node = listhead (chosen); node; nextnode (node))
90 if ((or = getdata (node)) != NULL)
91 if (or->cost < OSPF_LS_INFINITY)
92 {
93 if (best == NULL)
94 best = or;
95 else if (best->cost > or->cost)
96 best = or;
97 else if (best->cost == or->cost &&
98 IPV4_ADDR_CMP (&best->u.std.area_id,
99 &or->u.std.area_id) < 0)
100 best = or;
101 }
102
103 if (chosen != rn->info)
104 list_delete (chosen);
105
106 return best;
107}
108
109struct ospf_route *
110ospf_find_asbr_route_through_area (struct route_table *rtrs,
111 struct prefix_ipv4 *asbr,
112 struct ospf_area *area)
113{
114 struct route_node *rn;
115
116 /* Sanity check. */
117 if (rtrs == NULL)
118 return NULL;
119
120 rn = route_node_lookup (rtrs, (struct prefix *) asbr);
121
122 if (rn)
123 {
52dc7ee6 124 struct listnode *node;
718e3744 125 struct ospf_route *or;
126
127 route_unlock_node (rn);
128
52dc7ee6 129 for (node = listhead ((struct list *) rn->info); node; nextnode (node))
718e3744 130 if ((or = getdata (node)) != NULL)
131 if (IPV4_ADDR_SAME (&or->u.std.area_id, &area->area_id))
132 return or;
133 }
134
135 return NULL;
136}
137
138void
139ospf_ase_complete_direct_routes (struct ospf_route *ro, struct in_addr nexthop)
140{
52dc7ee6 141 struct listnode *node;
718e3744 142 struct ospf_path *op;
143
96735eea 144 for (node = listhead (ro->paths); node; nextnode (node))
718e3744 145 if ((op = getdata (node)) != NULL)
146 if (op->nexthop.s_addr == 0)
147 op->nexthop.s_addr = nexthop.s_addr;
148}
149
150int
68980084 151ospf_ase_forward_address_check (struct ospf *ospf, struct in_addr fwd_addr)
718e3744 152{
52dc7ee6 153 struct listnode *ifn;
718e3744 154 struct ospf_interface *oi;
155
68980084 156 for (ifn = listhead (ospf->oiflist); ifn; nextnode (ifn))
718e3744 157 if ((oi = getdata (ifn)) != NULL)
2e3b2e47 158 if (if_is_operative (oi->ifp))
718e3744 159 if (oi->type != OSPF_IFTYPE_VIRTUALLINK)
160 if (IPV4_ADDR_SAME (&oi->address->u.prefix4, &fwd_addr))
161 return 0;
162
163 return 1;
164}
165
166/* Calculate ASBR route. */
167struct ospf_route *
68980084 168ospf_ase_calculate_asbr_route (struct ospf *ospf,
169 struct route_table *rt_network,
718e3744 170 struct route_table *rt_router,
171 struct as_external_lsa *al)
172{
173 struct prefix_ipv4 asbr;
174 struct ospf_route *asbr_route;
175 struct route_node *rn;
176
177 /* Find ASBR route from Router routing table. */
178 asbr.family = AF_INET;
179 asbr.prefix = al->header.adv_router;
180 asbr.prefixlen = IPV4_MAX_BITLEN;
181 apply_mask_ipv4 (&asbr);
182
68980084 183 asbr_route = ospf_find_asbr_route (ospf, rt_router, &asbr);
718e3744 184
185 if (asbr_route == NULL)
186 {
e40dcce1 187 if (IS_DEBUG_OSPF (lsa, LSA))
188 zlog_debug ("ospf_ase_calculate(): Route to ASBR %s not found",
189 inet_ntoa (asbr.prefix));
718e3744 190 return NULL;
191 }
192
193 if (!(asbr_route->u.std.flags & ROUTER_LSA_EXTERNAL))
194 {
e40dcce1 195 if (IS_DEBUG_OSPF (lsa, LSA))
196 zlog_debug ("ospf_ase_calculate(): Originating router is not an ASBR");
718e3744 197 return NULL;
198 }
199
200 if (al->e[0].fwd_addr.s_addr != 0)
201 {
e40dcce1 202 if (IS_DEBUG_OSPF (lsa, LSA))
203 zlog_debug ("ospf_ase_calculate(): "
204 "Forwarding address is not 0.0.0.0.");
718e3744 205
68980084 206 if (! ospf_ase_forward_address_check (ospf, al->e[0].fwd_addr))
718e3744 207 {
e40dcce1 208 if (IS_DEBUG_OSPF (lsa, LSA))
209 zlog_debug ("ospf_ase_calculate(): "
210 "Forwarding address is one of our addresses, Ignore.");
718e3744 211 return NULL;
212 }
213
e40dcce1 214 if (IS_DEBUG_OSPF (lsa, LSA))
215 zlog_debug ("ospf_ase_calculate(): "
216 "Looking up in the Network Routing Table.");
718e3744 217
218 /* Looking up the path to the fwd_addr from Network route. */
219 asbr.family = AF_INET;
220 asbr.prefix = al->e[0].fwd_addr;
221 asbr.prefixlen = IPV4_MAX_BITLEN;
222
223 rn = route_node_match (rt_network, (struct prefix *) &asbr);
224
225 if (rn == NULL)
226 {
e40dcce1 227 if (IS_DEBUG_OSPF (lsa, LSA))
228 zlog_debug ("ospf_ase_calculate(): "
229 "Couldn't find a route to the forwarding address.");
718e3744 230 return NULL;
231 }
232
233 route_unlock_node (rn);
234
235 if ((asbr_route = rn->info) == NULL)
236 {
e40dcce1 237 if (IS_DEBUG_OSPF (lsa, LSA))
238 zlog_debug ("ospf_ase_calculate(): "
239 "Somehow OSPF route to ASBR is lost");
718e3744 240 return NULL;
241 }
242 }
243
244 return asbr_route;
245}
246
247struct ospf_route *
248ospf_ase_calculate_new_route (struct ospf_lsa *lsa,
249 struct ospf_route *asbr_route, u_int32_t metric)
250{
251 struct as_external_lsa *al;
252 struct ospf_route *new;
253
254 al = (struct as_external_lsa *) lsa->data;
255
256 new = ospf_route_new ();
257
258 /* Set redistributed type -- does make sense? */
259 /* new->type = type; */
260 new->id = al->header.id;
261 new->mask = al->mask;
262
263 if (!IS_EXTERNAL_METRIC (al->e[0].tos))
264 {
e40dcce1 265 if (IS_DEBUG_OSPF (lsa, LSA))
266 zlog_debug ("Route[External]: type-1 created.");
718e3744 267 new->path_type = OSPF_PATH_TYPE1_EXTERNAL;
268 new->cost = asbr_route->cost + metric; /* X + Y */
269 }
270 else
271 {
e40dcce1 272 if (IS_DEBUG_OSPF (lsa, LSA))
273 zlog_debug ("Route[External]: type-2 created.");
718e3744 274 new->path_type = OSPF_PATH_TYPE2_EXTERNAL;
275 new->cost = asbr_route->cost; /* X */
276 new->u.ext.type2_cost = metric; /* Y */
277 }
278
279 new->type = OSPF_DESTINATION_NETWORK;
718e3744 280 new->u.ext.origin = lsa;
281 new->u.ext.tag = ntohl (al->e[0].route_tag);
282 new->u.ext.asbr = asbr_route;
283
284 assert (new != asbr_route);
285
286 return new;
287}
288
289#define OSPF_ASE_CALC_INTERVAL 1
290
291int
68980084 292ospf_ase_calculate_route (struct ospf *ospf, struct ospf_lsa * lsa)
718e3744 293{
294 u_int32_t metric;
295 struct as_external_lsa *al;
296 struct ospf_route *asbr_route;
297 struct prefix_ipv4 asbr, p;
298 struct route_node *rn;
299 struct ospf_route *new, *or;
300 int ret;
301
302 assert (lsa);
303 al = (struct as_external_lsa *) lsa->data;
304
718e3744 305 if (lsa->data->type == OSPF_AS_NSSA_LSA)
306 if (IS_DEBUG_OSPF_NSSA)
e84cc647 307 zlog_debug ("ospf_ase_calc(): Processing Type-7");
718e3744 308
309 /* Stay away from any Local Translated Type-7 LSAs */
310 if (CHECK_FLAG (lsa->flags, OSPF_LSA_LOCAL_XLT))
311 {
312 if (IS_DEBUG_OSPF_NSSA)
e84cc647 313 zlog_debug ("ospf_ase_calc(): Rejecting Local Xlt'd");
718e3744 314 return 0;
315 }
718e3744 316
e40dcce1 317 if (IS_DEBUG_OSPF (lsa, LSA))
318 zlog_debug ("Route[External]: Calculate AS-external-LSA to %s/%d",
319 inet_ntoa (al->header.id), ip_masklen (al->mask));
718e3744 320 /* (1) If the cost specified by the LSA is LSInfinity, or if the
321 LSA's LS age is equal to MaxAge, then examine the next LSA. */
322 if ((metric = GET_METRIC (al->e[0].metric)) >= OSPF_LS_INFINITY)
323 {
e40dcce1 324 if (IS_DEBUG_OSPF (lsa, LSA))
325 zlog_debug ("Route[External]: Metric is OSPF_LS_INFINITY");
718e3744 326 return 0;
327 }
328 if (IS_LSA_MAXAGE (lsa))
329 {
e40dcce1 330 if (IS_DEBUG_OSPF (lsa, LSA))
331 zlog_debug ("Route[External]: AS-external-LSA is MAXAGE");
718e3744 332 return 0;
333 }
334
335 /* (2) If the LSA was originated by the calculating router itself,
336 examine the next LSA. */
337 if (IS_LSA_SELF (lsa))
338 {
e40dcce1 339 if (IS_DEBUG_OSPF (lsa, LSA))
340 zlog_debug ("Route[External]: AS-external-LSA is self originated");
718e3744 341 return 0;
342 }
343
344 /* (3) Call the destination described by the LSA N. N's address is
345 obtained by masking the LSA's Link State ID with the
346 network/subnet mask contained in the body of the LSA. Look
347 up the routing table entries (potentially one per attached
348 area) for the AS boundary router (ASBR) that originated the
349 LSA. If no entries exist for router ASBR (i.e., ASBR is
350 unreachable), do nothing with this LSA and consider the next
351 in the list. */
352
353 asbr.family = AF_INET;
354 asbr.prefix = al->header.adv_router;
355 asbr.prefixlen = IPV4_MAX_BITLEN;
356 apply_mask_ipv4 (&asbr);
357
68980084 358 asbr_route = ospf_find_asbr_route (ospf, ospf->new_rtrs, &asbr);
718e3744 359 if (asbr_route == NULL)
360 {
e40dcce1 361 if (IS_DEBUG_OSPF (lsa, LSA))
362 zlog_debug ("Route[External]: Can't find originating ASBR route");
718e3744 363 return 0;
364 }
365 if (!(asbr_route->u.std.flags & ROUTER_LSA_EXTERNAL))
366 {
e40dcce1 367 if (IS_DEBUG_OSPF (lsa, LSA))
368 zlog_debug ("Route[External]: Originating router is not an ASBR");
718e3744 369 return 0;
370 }
371
372 /* Else, this LSA describes an AS external path to destination
373 N. Examine the forwarding address specified in the AS-
374 external-LSA. This indicates the IP address to which
375 packets for the destination should be forwarded. */
376
377 if (al->e[0].fwd_addr.s_addr == 0)
378 {
379 /* If the forwarding address is set to 0.0.0.0, packets should
380 be sent to the ASBR itself. Among the multiple routing table
381 entries for the ASBR, select the preferred entry as follows.
382 If RFC1583Compatibility is set to "disabled", prune the set
383 of routing table entries for the ASBR as described in
384 Section 16.4.1. In any case, among the remaining routing
385 table entries, select the routing table entry with the least
386 cost; when there are multiple least cost routing table
387 entries the entry whose associated area has the largest OSPF
388 Area ID (when considered as an unsigned 32-bit integer) is
389 chosen. */
390
391 /* asbr_route already contains the requested route */
392 }
393 else
394 {
395 /* If the forwarding address is non-zero, look up the
396 forwarding address in the routing table.[24] The matching
397 routing table entry must specify an intra-area or inter-area
398 path; if no such path exists, do nothing with the LSA and
399 consider the next in the list. */
68980084 400 if (! ospf_ase_forward_address_check (ospf, al->e[0].fwd_addr))
718e3744 401 {
e40dcce1 402 if (IS_DEBUG_OSPF (lsa, LSA))
403 zlog_debug ("Route[External]: Forwarding address is our router "
404 "address");
718e3744 405 return 0;
406 }
407
408 asbr.family = AF_INET;
409 asbr.prefix = al->e[0].fwd_addr;
410 asbr.prefixlen = IPV4_MAX_BITLEN;
411
68980084 412 rn = route_node_match (ospf->new_table, (struct prefix *) &asbr);
718e3744 413
414 if (rn == NULL || (asbr_route = rn->info) == NULL)
415 {
e40dcce1 416 if (IS_DEBUG_OSPF (lsa, LSA))
417 zlog_debug ("Route[External]: Can't find route to forwarding "
418 "address");
718e3744 419 if (rn)
420 route_unlock_node (rn);
421 return 0;
422 }
423
424 route_unlock_node (rn);
425 }
426
427 /* (4) Let X be the cost specified by the preferred routing table
428 entry for the ASBR/forwarding address, and Y the cost
429 specified in the LSA. X is in terms of the link state
430 metric, and Y is a type 1 or 2 external metric. */
431
432
433 /* (5) Look up the routing table entry for the destination N. If
434 no entry exists for N, install the AS external path to N,
435 with next hop equal to the list of next hops to the
436 forwarding address, and advertising router equal to ASBR.
437 If the external metric type is 1, then the path-type is set
438 to type 1 external and the cost is equal to X+Y. If the
439 external metric type is 2, the path-type is set to type 2
440 external, the link state component of the route's cost is X,
441 and the type 2 cost is Y. */
442 new = ospf_ase_calculate_new_route (lsa, asbr_route, metric);
443
444 /* (6) Compare the AS external path described by the LSA with the
445 existing paths in N's routing table entry, as follows. If
446 the new path is preferred, it replaces the present paths in
447 N's routing table entry. If the new path is of equal
448 preference, it is added to N's routing table entry's list of
449 paths. */
450
451 /* Set prefix. */
452 p.family = AF_INET;
453 p.prefix = al->header.id;
454 p.prefixlen = ip_masklen (al->mask);
455
456 /* if there is a Intra/Inter area route to the N
457 do not install external route */
68980084 458 if ((rn = route_node_lookup (ospf->new_table,
718e3744 459 (struct prefix *) &p)) != NULL
460 && (rn->info != NULL))
461 {
462 if (new)
463 ospf_route_free (new);
464 return 0;
465 }
466
467 /* Find a route to the same dest */
468 /* If there is no route, create new one. */
68980084 469 if ((rn = route_node_lookup (ospf->new_external_route,
718e3744 470 (struct prefix *) &p)) == NULL
471 || (or = rn->info) == NULL)
472 {
e40dcce1 473 if (IS_DEBUG_OSPF (lsa, LSA))
474 zlog_debug ("Route[External]: Adding a new route %s/%d",
475 inet_ntoa (p.prefix), p.prefixlen);
718e3744 476
68980084 477 ospf_route_add (ospf->new_external_route, &p, new, asbr_route);
718e3744 478
479 if (al->e[0].fwd_addr.s_addr)
480 ospf_ase_complete_direct_routes (new, al->e[0].fwd_addr);
481 return 0;
482 }
483 else
484 {
485 /* (a) Intra-area and inter-area paths are always preferred
486 over AS external paths.
487
488 (b) Type 1 external paths are always preferred over type 2
489 external paths. When all paths are type 2 external
490 paths, the paths with the smallest advertised type 2
491 metric are always preferred. */
68980084 492 ret = ospf_route_cmp (ospf, new, or);
718e3744 493
494 /* (c) If the new AS external path is still indistinguishable
495 from the current paths in the N's routing table entry,
496 and RFC1583Compatibility is set to "disabled", select
497 the preferred paths based on the intra-AS paths to the
498 ASBR/forwarding addresses, as specified in Section
499 16.4.1.
500
501 (d) If the new AS external path is still indistinguishable
502 from the current paths in the N's routing table entry,
503 select the preferred path based on a least cost
504 comparison. Type 1 external paths are compared by
505 looking at the sum of the distance to the forwarding
506 address and the advertised type 1 metric (X+Y). Type 2
507 external paths advertising equal type 2 metrics are
508 compared by looking at the distance to the forwarding
509 addresses.
510 */
511 /* New route is better */
512 if (ret < 0)
513 {
e40dcce1 514 if (IS_DEBUG_OSPF (lsa, LSA))
515 zlog_debug ("Route[External]: New route is better");
718e3744 516 ospf_route_subst (rn, new, asbr_route);
517 if (al->e[0].fwd_addr.s_addr)
518 ospf_ase_complete_direct_routes (new, al->e[0].fwd_addr);
519 or = new;
520 new = NULL;
521 }
522 /* Old route is better */
523 else if (ret > 0)
524 {
e40dcce1 525 if (IS_DEBUG_OSPF (lsa, LSA))
526 zlog_debug ("Route[External]: Old route is better");
718e3744 527 /* do nothing */
528 }
529 /* Routes are equal */
530 else
531 {
e40dcce1 532 if (IS_DEBUG_OSPF (lsa, LSA))
533 zlog_debug ("Route[External]: Routes are equal");
96735eea 534 ospf_route_copy_nexthops (or, asbr_route->paths);
718e3744 535 if (al->e[0].fwd_addr.s_addr)
536 ospf_ase_complete_direct_routes (or, al->e[0].fwd_addr);
537 }
538 }
539 /* Make sure setting newly calculated ASBR route.*/
540 or->u.ext.asbr = asbr_route;
541 if (new)
542 ospf_route_free (new);
543
544 lsa->route = or;
545 return 0;
546}
547
548int
549ospf_ase_route_match_same (struct route_table *rt, struct prefix *prefix,
550 struct ospf_route *newor)
551{
552 struct route_node *rn;
553 struct ospf_route *or;
554 struct ospf_path *op;
555 struct ospf_path *newop;
52dc7ee6 556 struct listnode *n1;
557 struct listnode *n2;
718e3744 558
559 if (! rt || ! prefix)
560 return 0;
561
562 rn = route_node_lookup (rt, prefix);
563 if (! rn)
564 return 0;
565
566 route_unlock_node (rn);
567
568 or = rn->info;
569 if (or->path_type != newor->path_type)
570 return 0;
571
572 switch (or->path_type)
573 {
574 case OSPF_PATH_TYPE1_EXTERNAL:
575 if (or->cost != newor->cost)
576 return 0;
577 break;
578 case OSPF_PATH_TYPE2_EXTERNAL:
579 if ((or->cost != newor->cost) ||
580 (or->u.ext.type2_cost != newor->u.ext.type2_cost))
581 return 0;
582 break;
583 default:
584 assert (0);
585 return 0;
586 }
587
96735eea 588 if (or->paths->count != newor->paths->count)
718e3744 589 return 0;
590
591 /* Check each path. */
96735eea 592 for (n1 = listhead (or->paths), n2 = listhead (newor->paths);
718e3744 593 n1 && n2; nextnode (n1), nextnode (n2))
594 {
595 op = getdata (n1);
596 newop = getdata (n2);
597
598 if (! IPV4_ADDR_SAME (&op->nexthop, &newop->nexthop))
599 return 0;
600 }
601 return 1;
602}
603
604int
605ospf_ase_compare_tables (struct route_table *new_external_route,
606 struct route_table *old_external_route)
607{
608 struct route_node *rn, *new_rn;
609 struct ospf_route *or;
610
611 /* Remove deleted routes */
612 for (rn = route_top (old_external_route); rn; rn = route_next (rn))
613 if ((or = rn->info))
614 {
615 if (! (new_rn = route_node_lookup (new_external_route, &rn->p)))
616 ospf_zebra_delete ((struct prefix_ipv4 *) &rn->p, or);
617 else
618 route_unlock_node (new_rn);
619 }
620
621
622 /* Install new routes */
623 for (rn = route_top (new_external_route); rn; rn = route_next (rn))
624 if ((or = rn->info) != NULL)
625 if (! ospf_ase_route_match_same (old_external_route, &rn->p, or))
626 ospf_zebra_add ((struct prefix_ipv4 *) &rn->p, or);
627
628 return 0;
629}
630
631int
632ospf_ase_calculate_timer (struct thread *t)
633{
634 struct ospf *ospf;
68980084 635 struct ospf_lsa *lsa;
636 struct route_node *rn;
52dc7ee6 637 struct listnode *node;
68980084 638 struct ospf_area *area;
718e3744 639
640 ospf = THREAD_ARG (t);
641 ospf->t_ase_calc = NULL;
642
643 if (ospf->ase_calc)
644 {
645 ospf->ase_calc = 0;
646
647 /* Calculate external route for each AS-external-LSA */
68980084 648 LSDB_LOOP (EXTERNAL_LSDB (ospf), rn, lsa)
649 ospf_ase_calculate_route (ospf, lsa);
718e3744 650
718e3744 651 /* This version simple adds to the table all NSSA areas */
68980084 652 if (ospf->anyNSSA)
653 for (node = listhead (ospf->areas); node; nextnode (node))
718e3744 654 {
655 area = getdata (node);
656 if (IS_DEBUG_OSPF_NSSA)
e84cc647 657 zlog_debug ("ospf_ase_calculate_timer(): looking at area %s",
718e3744 658 inet_ntoa (area->area_id));
659
660 if (area->external_routing == OSPF_AREA_NSSA)
68980084 661 LSDB_LOOP (NSSA_LSDB (area), rn, lsa)
662 ospf_ase_calculate_route (ospf, lsa);
718e3744 663 }
f2c80652 664 /* kevinm: And add the NSSA routes in ospf_top */
f6386eeb 665 LSDB_LOOP (NSSA_LSDB (ospf),rn,lsa)
666 ospf_ase_calculate_route(ospf,lsa);
f2c80652 667
718e3744 668 /* Compare old and new external routing table and install the
669 difference info zebra/kernel */
68980084 670 ospf_ase_compare_tables (ospf->new_external_route,
671 ospf->old_external_route);
718e3744 672
673 /* Delete old external routing table */
68980084 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 ();
718e3744 677 }
678 return 0;
679}
680
681void
68980084 682ospf_ase_calculate_schedule (struct ospf *ospf)
718e3744 683{
68980084 684 if (ospf == NULL)
718e3744 685 return;
686
68980084 687 ospf->ase_calc = 1;
718e3744 688}
689
690void
68980084 691ospf_ase_calculate_timer_add (struct ospf *ospf)
718e3744 692{
68980084 693 if (ospf == NULL)
718e3744 694 return;
695
68980084 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);
718e3744 699}
700
701void
702ospf_ase_register_external_lsa (struct ospf_lsa *lsa, struct ospf *top)
703{
704 struct route_node *rn;
705 struct prefix_ipv4 p;
52dc7ee6 706 struct list *lst;
718e3744 707 struct as_external_lsa *al;
708
709 al = (struct as_external_lsa *) lsa->data;
710 p.family = AF_INET;
711 p.prefix = lsa->data->id;
712 p.prefixlen = ip_masklen (al->mask);
713 apply_mask_ipv4 (&p);
714
715 rn = route_node_get (top->external_lsas, (struct prefix *) &p);
716 if ((lst = rn->info) == NULL)
717 rn->info = lst = list_new();
718
719 /* We assume that if LSA is deleted from DB
720 is is also deleted from this RT */
721
722 listnode_add (lst, ospf_lsa_lock (lsa));
723}
724
725void
726ospf_ase_unregister_external_lsa (struct ospf_lsa *lsa, struct ospf *top)
727{
728 struct route_node *rn;
729 struct prefix_ipv4 p;
52dc7ee6 730 struct list *lst;
718e3744 731 struct as_external_lsa *al;
732
733 al = (struct as_external_lsa *) lsa->data;
734 p.family = AF_INET;
735 p.prefix = lsa->data->id;
736 p.prefixlen = ip_masklen (al->mask);
737 apply_mask_ipv4 (&p);
738
739 rn = route_node_get (top->external_lsas, (struct prefix *) &p);
740 lst = rn->info;
741#ifdef ORIGINAL_CODING
742 assert (lst);
743
744 listnode_delete (lst, lsa);
745 ospf_lsa_unlock (lsa);
746#else /* ORIGINAL_CODING */
747 /* XXX lst can be NULL */
748 if (lst) {
749 listnode_delete (lst, lsa);
750 ospf_lsa_unlock (lsa);
751 }
752#endif /* ORIGINAL_CODING */
753}
754
755void
756ospf_ase_external_lsas_finish (struct route_table *rt)
757{
758 struct route_node *rn;
759 struct ospf_lsa *lsa;
52dc7ee6 760 struct list *lst;
761 struct listnode *node;
718e3744 762
763 for (rn = route_top (rt); rn; rn = route_next (rn))
764 if ((lst = rn->info) != NULL)
765 {
766 for (node = listhead (lst); node; node = nextnode (node))
767 if ((lsa = getdata (node)) != NULL)
768 ospf_lsa_unlock (lsa);
769 list_delete (lst);
770 }
771
772 route_table_finish (rt);
773}
774
775void
68980084 776ospf_ase_incremental_update (struct ospf *ospf, struct ospf_lsa *lsa)
718e3744 777{
52dc7ee6 778 struct list *lsas;
779 struct listnode *node;
718e3744 780 struct route_node *rn, *rn2;
781 struct prefix_ipv4 p;
782 struct route_table *tmp_old;
783 struct as_external_lsa *al;
784
785 al = (struct as_external_lsa *) lsa->data;
786 p.family = AF_INET;
787 p.prefix = lsa->data->id;
788 p.prefixlen = ip_masklen (al->mask);
789 apply_mask_ipv4 (&p);
790
791 /* if new_table is NULL, there was no spf calculation, thus
792 incremental update is unneeded */
68980084 793 if (!ospf->new_table)
718e3744 794 return;
795
796 /* If there is already an intra-area or inter-area route
797 to the destination, no recalculation is necessary
798 (internal routes take precedence). */
799
68980084 800 rn = route_node_lookup (ospf->new_table, (struct prefix *) &p);
718e3744 801 if (rn && rn->info)
802 {
803 route_unlock_node (rn);
804 return;
805 }
806
68980084 807 rn = route_node_lookup (ospf->external_lsas, (struct prefix *) &p);
718e3744 808 assert (rn && rn->info);
809 lsas = rn->info;
810
811 for (node = listhead (lsas); node; nextnode (node))
812 if ((lsa = getdata (node)) != NULL)
68980084 813 ospf_ase_calculate_route (ospf, lsa);
718e3744 814
815 /* prepare temporary old routing table for compare */
816 tmp_old = route_table_init ();
68980084 817 rn = route_node_lookup (ospf->old_external_route, (struct prefix *) &p);
718e3744 818 if (rn && rn->info)
819 {
820 rn2 = route_node_get (tmp_old, (struct prefix *) &p);
821 rn2->info = rn->info;
822 }
823
824 /* install changes to zebra */
68980084 825 ospf_ase_compare_tables (ospf->new_external_route, tmp_old);
718e3744 826
68980084 827 /* update ospf->old_external_route table */
718e3744 828 if (rn && rn->info)
829 ospf_route_free ((struct ospf_route *) rn->info);
830
68980084 831 rn2 = route_node_lookup (ospf->new_external_route, (struct prefix *) &p);
832 /* if new route exists, install it to ospf->old_external_route */
718e3744 833 if (rn2 && rn2->info)
834 {
835 if (!rn)
68980084 836 rn = route_node_get (ospf->old_external_route, (struct prefix *) &p);
718e3744 837 rn->info = rn2->info;
838 }
839 else
840 {
68980084 841 /* remove route node from ospf->old_external_route */
718e3744 842 if (rn)
843 {
844 rn->info = NULL;
845 route_unlock_node (rn);
846 route_unlock_node (rn);
847 }
848 }
849
850 if (rn2)
851 {
68980084 852 /* rn2->info is stored in route node of ospf->old_external_route */
718e3744 853 rn2->info = NULL;
854 route_unlock_node (rn2);
855 route_unlock_node (rn2);
856 }
857
858 route_table_finish (tmp_old);
859}