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