blob: 0de415ee2505024b2441394532a57d8162aefad2 [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/*
2 * OSPF routing table.
3 * Copyright (C) 1999, 2000 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 "prefix.h"
26#include "table.h"
27#include "memory.h"
28#include "linklist.h"
29#include "log.h"
30#include "if.h"
31#include "command.h"
32#include "sockunion.h"
33
34#include "ospfd/ospfd.h"
35#include "ospfd/ospf_interface.h"
36#include "ospfd/ospf_asbr.h"
37#include "ospfd/ospf_lsa.h"
38#include "ospfd/ospf_route.h"
39#include "ospfd/ospf_spf.h"
40#include "ospfd/ospf_zebra.h"
41#include "ospfd/ospf_dump.h"
42
43struct ospf_route *
44ospf_route_new ()
45{
46 struct ospf_route *new;
47
48 new = XCALLOC (MTYPE_OSPF_ROUTE, sizeof (struct ospf_route));
49
50 new->ctime = time (NULL);
51 new->mtime = new->ctime;
52
53 return new;
54}
55
56void
57ospf_route_free (struct ospf_route *or)
58{
59 listnode node;
60
61 if (or->path)
62 {
63 for (node = listhead (or->path); node; nextnode (node))
64 ospf_path_free (node->data);
65
66 list_delete (or->path);
67 }
68
69 XFREE (MTYPE_OSPF_ROUTE, or);
70}
71
72struct ospf_path *
73ospf_path_new ()
74{
75 struct ospf_path *new;
76
77 new = XCALLOC (MTYPE_OSPF_PATH, sizeof (struct ospf_path));
78
79 return new;
80}
81
82struct ospf_path *
83ospf_path_dup (struct ospf_path *path)
84{
85 struct ospf_path *new;
86
87 new = ospf_path_new ();
88 memcpy (new, path, sizeof (struct ospf_path));
89
90 return new;
91}
92
93void
94ospf_path_free (struct ospf_path *op)
95{
96 XFREE (MTYPE_OSPF_PATH, op);
97}
98
99void
100ospf_route_delete (struct route_table *rt)
101{
102 struct route_node *rn;
103 struct ospf_route *or;
104
105 for (rn = route_top (rt); rn; rn = route_next (rn))
106 if ((or = rn->info) != NULL)
107 {
108 if (or->type == OSPF_DESTINATION_NETWORK)
109 ospf_zebra_delete ((struct prefix_ipv4 *) &rn->p,
110 or);
111 else if (or->type == OSPF_DESTINATION_DISCARD)
112 ospf_zebra_delete_discard ((struct prefix_ipv4 *) &rn->p);
113 }
114}
115
116void
117ospf_route_table_free (struct route_table *rt)
118{
119 struct route_node *rn;
120 struct ospf_route *or;
121
122 for (rn = route_top (rt); rn; rn = route_next (rn))
123 if ((or = rn->info) != NULL)
124 {
125 ospf_route_free (or);
126
127 rn->info = NULL;
128 route_unlock_node (rn);
129 }
130
131 route_table_finish (rt);
132}
133
134/* If a prefix and a nexthop match any route in the routing table,
135 then return 1, otherwise return 0. */
136int
137ospf_route_match_same (struct route_table *rt, struct prefix_ipv4 *prefix,
138 struct ospf_route *newor)
139{
140 struct route_node *rn;
141 struct ospf_route *or;
142 struct ospf_path *op;
143 struct ospf_path *newop;
144 listnode n1;
145 listnode n2;
146
147 if (! rt || ! prefix)
148 return 0;
149
150 rn = route_node_lookup (rt, (struct prefix *) prefix);
151 if (! rn || ! rn->info)
152 return 0;
153
154 route_unlock_node (rn);
155
156 or = rn->info;
157 if (or->type == newor->type && or->cost == newor->cost)
158 {
159 if (or->type == OSPF_DESTINATION_NETWORK)
160 {
161 if (or->path->count != newor->path->count)
162 return 0;
163
164 /* Check each path. */
165 for (n1 = listhead (or->path), n2 = listhead (newor->path);
166 n1 && n2; nextnode (n1), nextnode (n2))
167 {
168 op = getdata (n1);
169 newop = getdata (n2);
170
171 if (! IPV4_ADDR_SAME (&op->nexthop, &newop->nexthop))
172 return 0;
173 }
174 return 1;
175 }
176 else if (prefix_same (&rn->p, (struct prefix *) prefix))
177 return 1;
178 }
179 return 0;
180}
181
paul6d1fab62003-06-22 08:28:18 +0000182/* delete routes generated from AS-External routes if there is a inter/intra
183 * area route
184 */
185void
186ospf_route_delete_same_ext(struct route_table *external_routes,
187 struct route_table *routes)
188{
189 struct route_node *rn,
190 *ext_rn;
191
192 if ( (external_routes == NULL) || (routes == NULL) )
193 return;
194
195 /* Remove deleted routes */
196 for ( rn = route_top (routes); rn; rn = route_next (rn) )
197 {
198 if (rn && rn->info)
199 {
200 struct prefix_ipv4 *p = &rn->p;
201 if ( (ext_rn = route_node_lookup (external_routes, p)) )
202 {
203 ospf_zebra_delete (p, ext_rn->info);
204 if (ext_rn->info)
205 {
206 ospf_route_free( ext_rn->info);
207 ext_rn->info = NULL;
208 }
209 route_unlock_node (ext_rn);
210 }
211 }
212 }
213}
214
paul718e3742002-12-13 20:15:29 +0000215/* rt: Old, cmprt: New */
216void
217ospf_route_delete_uniq (struct route_table *rt, struct route_table *cmprt)
218{
219 struct route_node *rn;
220 struct ospf_route *or;
221
222 for (rn = route_top (rt); rn; rn = route_next (rn))
223 if ((or = rn->info) != NULL)
224 if (or->path_type == OSPF_PATH_INTRA_AREA ||
225 or->path_type == OSPF_PATH_INTER_AREA)
226 {
227 if (or->type == OSPF_DESTINATION_NETWORK)
228 {
229 if (! ospf_route_match_same (cmprt,
230 (struct prefix_ipv4 *) &rn->p, or))
231 ospf_zebra_delete ((struct prefix_ipv4 *) &rn->p, or);
232 }
233 else if (or->type == OSPF_DESTINATION_DISCARD)
234 if (! ospf_route_match_same (cmprt,
235 (struct prefix_ipv4 *) &rn->p, or))
236 ospf_zebra_delete_discard ((struct prefix_ipv4 *) &rn->p);
237 }
238}
239
240/* Install routes to table. */
241void
paul6d1fab62003-06-22 08:28:18 +0000242ospf_route_install (struct ospf *ospf, struct route_table *rt)
paul718e3742002-12-13 20:15:29 +0000243{
244 struct route_node *rn;
245 struct ospf_route *or;
246
247 /* rt contains new routing table, new_table contains an old one.
248 updating pointers */
paul6d1fab62003-06-22 08:28:18 +0000249 if (ospf->old_table)
250 ospf_route_table_free (ospf->old_table);
251
252 ospf->old_table = ospf->new_table;
253 ospf->new_table = rt;
paul718e3742002-12-13 20:15:29 +0000254
255 /* Delete old routes. */
paul6d1fab62003-06-22 08:28:18 +0000256 if (ospf->old_table)
257 ospf_route_delete_uniq (ospf->old_table, rt);
258 if (ospf->old_external_route)
259 ospf_route_delete_same_ext (ospf->old_external_route, rt);
paul718e3742002-12-13 20:15:29 +0000260
261 /* Install new routes. */
262 for (rn = route_top (rt); rn; rn = route_next (rn))
263 if ((or = rn->info) != NULL)
264 {
265 if (or->type == OSPF_DESTINATION_NETWORK)
266 {
paul6d1fab62003-06-22 08:28:18 +0000267 if (! ospf_route_match_same (ospf->old_table,
paul718e3742002-12-13 20:15:29 +0000268 (struct prefix_ipv4 *)&rn->p, or))
269 ospf_zebra_add ((struct prefix_ipv4 *) &rn->p, or);
270 }
271 else if (or->type == OSPF_DESTINATION_DISCARD)
paul6d1fab62003-06-22 08:28:18 +0000272 if (! ospf_route_match_same (ospf->old_table,
paul718e3742002-12-13 20:15:29 +0000273 (struct prefix_ipv4 *) &rn->p, or))
274 ospf_zebra_add_discard ((struct prefix_ipv4 *) &rn->p);
275 }
276}
277
278void
279ospf_intra_route_add (struct route_table *rt, struct vertex *v,
280 struct ospf_area *area)
281{
282 struct route_node *rn;
283 struct ospf_route *or;
284 struct prefix_ipv4 p;
285 struct ospf_path *path;
286 struct vertex_nexthop *nexthop;
287 listnode nnode;
288
289 p.family = AF_INET;
290 p.prefix = v->id;
291 if (v->type == OSPF_VERTEX_ROUTER)
292 p.prefixlen = IPV4_MAX_BITLEN;
293 else
294 {
295 struct network_lsa *lsa = (struct network_lsa *) v->lsa;
296 p.prefixlen = ip_masklen (lsa->mask);
297 }
298 apply_mask_ipv4 (&p);
299
300 rn = route_node_get (rt, (struct prefix *) &p);
301 if (rn->info)
302 {
303 zlog_warn ("Same routing information exists for %s", inet_ntoa (v->id));
304 route_unlock_node (rn);
305 return;
306 }
307
308 or = ospf_route_new ();
309
310 if (v->type == OSPF_VERTEX_NETWORK)
311 {
312 or->type = OSPF_DESTINATION_NETWORK;
313 or->path = list_new ();
314
315 for (nnode = listhead (v->nexthop); nnode; nextnode (nnode))
316 {
317 nexthop = getdata (nnode);
318 path = ospf_path_new ();
319 path->nexthop = nexthop->router;
320 listnode_add (or->path, path);
321 }
322 }
323 else
324 or->type = OSPF_DESTINATION_ROUTER;
325
326 or->id = v->id;
327 or->u.std.area_id = area->area_id;
328#ifdef HAVE_NSSA
329 or->u.std.external_routing= area->external_routing;
330#endif /* HAVE_NSSA */
331 or->path_type = OSPF_PATH_INTRA_AREA;
332 or->cost = v->distance;
333
334 rn->info = or;
335}
336
337/* RFC2328 16.1. (4). For "router". */
338void
339ospf_intra_add_router (struct route_table *rt, struct vertex *v,
340 struct ospf_area *area)
341{
342 struct route_node *rn;
343 struct ospf_route *or;
344 struct prefix_ipv4 p;
345 struct router_lsa *lsa;
346
347 if (IS_DEBUG_OSPF_EVENT)
348 zlog_info ("ospf_intra_add_router: Start");
349
350 lsa = (struct router_lsa *) v->lsa;
351
352 if (IS_DEBUG_OSPF_EVENT)
353 zlog_info ("ospf_intra_add_router: LS ID: %s",
354 inet_ntoa (lsa->header.id));
355
356 ospf_vl_up_check (area, lsa->header.id, v);
357
358 if (!CHECK_FLAG (lsa->flags, ROUTER_LSA_SHORTCUT))
359 area->shortcut_capability = 0;
360
361 /* If the newly added vertex is an area border router or AS boundary
362 router, a routing table entry is added whose destination type is
363 "router". */
364 if (! IS_ROUTER_LSA_BORDER (lsa) && ! IS_ROUTER_LSA_EXTERNAL (lsa))
365 {
366 if (IS_DEBUG_OSPF_EVENT)
367 zlog_info ("ospf_intra_add_router: "
368 "this router is neither ASBR nor ABR, skipping it");
369 return;
370 }
371
372 /* Update ABR and ASBR count in this area. */
373 if (IS_ROUTER_LSA_BORDER (lsa))
374 area->abr_count++;
375 if (IS_ROUTER_LSA_EXTERNAL (lsa))
376 area->asbr_count++;
377
378 /* The Options field found in the associated router-LSA is copied
379 into the routing table entry's Optional capabilities field. Call
380 the newly added vertex Router X. */
381 or = ospf_route_new ();
382
383 or->id = v->id;
384 or->u.std.area_id = area->area_id;
385#ifdef HAVE_NSSA
386 or->u.std.external_routing = area->external_routing;
387#endif /* HAVE_NSSA */
388 or->path_type = OSPF_PATH_INTRA_AREA;
389 or->cost = v->distance;
390 or->type = OSPF_DESTINATION_ROUTER;
391 or->u.std.origin = (struct lsa_header *) lsa;
392 or->u.std.options = lsa->header.options;
393 or->u.std.flags = lsa->flags;
394
395 /* If Router X is the endpoint of one of the calculating router's
396 virtual links, and the virtual link uses Area A as Transit area:
397 the virtual link is declared up, the IP address of the virtual
398 interface is set to the IP address of the outgoing interface
399 calculated above for Router X, and the virtual neighbor's IP
400 address is set to Router X's interface address (contained in
401 Router X's router-LSA) that points back to the root of the
402 shortest- path tree; equivalently, this is the interface that
403 points back to Router X's parent vertex on the shortest-path tree
404 (similar to the calculation in Section 16.1.1). */
405
406 p.family = AF_INET;
407 p.prefix = v->id;
408 p.prefixlen = IPV4_MAX_BITLEN;
409
410 if (IS_DEBUG_OSPF_EVENT)
411 zlog_info ("ospf_intra_add_router: talking about %s/%d",
412 inet_ntoa (p.prefix), p.prefixlen);
413
414 rn = route_node_get (rt, (struct prefix *) &p);
415
416 /* Note that we keep all routes to ABRs and ASBRs, not only the best */
417 if (rn->info == NULL)
418 rn->info = list_new ();
419 else
420 route_unlock_node (rn);
421
422 ospf_route_copy_nexthops_from_vertex (or, v);
423
424 listnode_add (rn->info, or);
425
426 zlog_info ("ospf_intra_add_router: Start");
427}
428
429/* RFC2328 16.1. (4). For transit network. */
430void
431ospf_intra_add_transit (struct route_table *rt, struct vertex *v,
432 struct ospf_area *area)
433{
434 struct route_node *rn;
435 struct ospf_route *or;
436 struct prefix_ipv4 p;
437 struct network_lsa *lsa;
438
439 lsa = (struct network_lsa*) v->lsa;
440
441 /* If the newly added vertex is a transit network, the routing table
442 entry for the network is located. The entry's Destination ID is
443 the IP network number, which can be obtained by masking the
444 Vertex ID (Link State ID) with its associated subnet mask (found
445 in the body of the associated network-LSA). */
446 p.family = AF_INET;
447 p.prefix = v->id;
448 p.prefixlen = ip_masklen (lsa->mask);
449 apply_mask_ipv4 (&p);
450
451 rn = route_node_get (rt, (struct prefix *) &p);
452
453 /* If the routing table entry already exists (i.e., there is already
454 an intra-area route to the destination installed in the routing
455 table), multiple vertices have mapped to the same IP network.
456 For example, this can occur when a new Designated Router is being
457 established. In this case, the current routing table entry
458 should be overwritten if and only if the newly found path is just
459 as short and the current routing table entry's Link State Origin
460 has a smaller Link State ID than the newly added vertex' LSA. */
461 if (rn->info)
462 {
463 struct ospf_route *cur_or;
464
465 route_unlock_node (rn);
466 cur_or = rn->info;
467
468 if (v->distance > cur_or->cost ||
469 IPV4_ADDR_CMP (&cur_or->u.std.origin->id, &lsa->header.id) > 0)
470 return;
471
472 ospf_route_free (rn->info);
473 }
474
475 or = ospf_route_new ();
476
477 or->id = v->id;
478 or->u.std.area_id = area->area_id;
479#ifdef HAVE_NSSA
480 or->u.std.external_routing = area->external_routing;
481#endif /* HAVE_NSSA */
482 or->path_type = OSPF_PATH_INTRA_AREA;
483 or->cost = v->distance;
484 or->type = OSPF_DESTINATION_NETWORK;
485 or->u.std.origin = (struct lsa_header *) lsa;
486
487 ospf_route_copy_nexthops_from_vertex (or, v);
488
489 rn->info = or;
490}
491
492/* RFC2328 16.1. second stage. */
493void
494ospf_intra_add_stub (struct route_table *rt, struct router_lsa_link *link,
495 struct vertex *v, struct ospf_area *area)
496{
497 u_int32_t cost;
498 struct route_node *rn;
499 struct ospf_route *or;
500 struct prefix_ipv4 p;
501 struct router_lsa *lsa;
502 struct ospf_interface *oi;
503 struct ospf_path *path;
504
505 if (IS_DEBUG_OSPF_EVENT)
506 zlog_info ("ospf_intra_add_stub(): Start");
507
508 lsa = (struct router_lsa *) v->lsa;
509
510 p.family = AF_INET;
511 p.prefix = link->link_id;
512 p.prefixlen = ip_masklen (link->link_data);
513 apply_mask_ipv4 (&p);
514
515 if (IS_DEBUG_OSPF_EVENT)
516 zlog_info ("ospf_intra_add_stub(): processing route to %s/%d",
517 inet_ntoa (p.prefix), p.prefixlen);
518
519 /* (1) Calculate the distance D of stub network from the root. D is
520 equal to the distance from the root to the router vertex
521 (calculated in stage 1), plus the stub network link's advertised
522 cost. */
523 cost = v->distance + ntohs (link->m[0].metric);
524
525 if (IS_DEBUG_OSPF_EVENT)
526 zlog_info ("ospf_intra_add_stub(): calculated cost is %d + %d = %d",
527 v->distance, ntohs(link->m[0].metric), cost);
528
529 rn = route_node_get (rt, (struct prefix *) &p);
530
531 /* Lookup current routing table. */
532 if (rn->info)
533 {
534 struct ospf_route *cur_or;
535
536 route_unlock_node (rn);
537
538 cur_or = rn->info;
539
540 if (IS_DEBUG_OSPF_EVENT)
541 zlog_info ("ospf_intra_add_stub(): "
542 "another route to the same prefix found");
543
544 /* Compare this distance to the current best cost to the stub
545 network. This is done by looking up the stub network's
546 current routing table entry. If the calculated distance D is
547 larger, go on to examine the next stub network link in the
548 LSA. */
549 if (cost > cur_or->cost)
550 {
551 if (IS_DEBUG_OSPF_EVENT)
552 zlog_info ("ospf_intra_add_stub(): old route is better, exit");
553 return;
554 }
555
556 /* (2) If this step is reached, the stub network's routing table
557 entry must be updated. Calculate the set of next hops that
558 would result from using the stub network link. This
559 calculation is shown in Section 16.1.1; input to this
560 calculation is the destination (the stub network) and the
561 parent vertex (the router vertex). If the distance D is the
562 same as the current routing table cost, simply add this set
563 of next hops to the routing table entry's list of next hops.
564 In this case, the routing table already has a Link State
565 Origin. If this Link State Origin is a router-LSA whose Link
566 State ID is smaller than V's Router ID, reset the Link State
567 Origin to V's router-LSA. */
568
569 if (cost == cur_or->cost)
570 {
571 if (IS_DEBUG_OSPF_EVENT)
572 zlog_info ("ospf_intra_add_stub(): routes are equal, merge");
573
574 ospf_route_copy_nexthops_from_vertex (cur_or, v);
575
576 if (IPV4_ADDR_CMP (&cur_or->u.std.origin->id, &lsa->header.id) < 0)
577 cur_or->u.std.origin = (struct lsa_header *) lsa;
578 return;
579 }
580
581 /* Otherwise D is smaller than the routing table cost.
582 Overwrite the current routing table entry by setting the
583 routing table entry's cost to D, and by setting the entry's
584 list of next hops to the newly calculated set. Set the
585 routing table entry's Link State Origin to V's router-LSA.
586 Then go on to examine the next stub network link. */
587
588 if (cost < cur_or->cost)
589 {
590 if (IS_DEBUG_OSPF_EVENT)
591 zlog_info ("ospf_intra_add_stub(): new route is better, set it");
592
593 cur_or->cost = cost;
594
595 list_delete (cur_or->path);
596 cur_or->path = NULL;
597
598 ospf_route_copy_nexthops_from_vertex (cur_or, v);
599
600 cur_or->u.std.origin = (struct lsa_header *) lsa;
601 return;
602 }
603 }
604
605 if (IS_DEBUG_OSPF_EVENT)
606 zlog_info ("ospf_intra_add_stub(): installing new route");
607
608 or = ospf_route_new ();
609
610 or->id = v->id;
611 or->u.std.area_id = area->area_id;
612#ifdef HAVE_NSSA
613 or->u.std.external_routing = area->external_routing;
614#endif /* HAVE_NSSA */
615 or->path_type = OSPF_PATH_INTRA_AREA;
616 or->cost = cost;
617 or->type = OSPF_DESTINATION_NETWORK;
618 or->u.std.origin = (struct lsa_header *) lsa;
619 or->path = list_new ();
620
621 /* Nexthop is depend on connection type. */
622 if (v != area->spf)
623 {
624 if (IS_DEBUG_OSPF_EVENT)
625 zlog_info ("ospf_intra_add_stub(): this network is on remote router");
626 ospf_route_copy_nexthops_from_vertex (or, v);
627 }
628 else
629 {
630 if (IS_DEBUG_OSPF_EVENT)
631 zlog_info ("ospf_intra_add_stub(): this network is on this router");
632
paul6d1fab62003-06-22 08:28:18 +0000633 if ((oi = ospf_if_lookup_by_prefix (area->ospf, &p)))
paul718e3742002-12-13 20:15:29 +0000634 {
635 if (IS_DEBUG_OSPF_EVENT)
636 zlog_info ("ospf_intra_add_stub(): the interface is %s",
637 IF_NAME (oi));
638
639 path = ospf_path_new ();
640 path->nexthop.s_addr = 0;
641 path->oi = oi;
642 listnode_add (or->path, path);
643 }
644 else
645 {
646 if (IS_DEBUG_OSPF_EVENT)
647 zlog_info ("ospf_intra_add_stub(): where's the interface ?");
648 }
649 }
650
651 rn->info = or;
652
653 if (IS_DEBUG_OSPF_EVENT)
654 zlog_info("ospf_intra_add_stub(): Stop");
655}
656
657char *ospf_path_type_str[] =
658{
659 "unknown-type",
660 "intra-area",
661 "inter-area",
662 "type1-external",
663 "type2-external"
664};
665
666void
667ospf_route_table_dump (struct route_table *rt)
668{
669 struct route_node *rn;
670 struct ospf_route *or;
671 char buf1[BUFSIZ];
672 char buf2[BUFSIZ];
673 listnode pnode;
674 struct ospf_path *path;
675
676#if 0
677 zlog_info ("Type Dest Area Path Type Cost Next Adv.");
678 zlog_info (" Hop(s) Router(s)");
679#endif /* 0 */
680
681 zlog_info ("========== OSPF routing table ==========");
682 for (rn = route_top (rt); rn; rn = route_next (rn))
683 if ((or = rn->info) != NULL)
684 {
685 if (or->type == OSPF_DESTINATION_NETWORK)
686 {
687 zlog_info ("N %s/%d\t%s\t%s\t%d",
688 inet_ntop (AF_INET, &rn->p.u.prefix4, buf1, BUFSIZ),
689 rn->p.prefixlen,
690 inet_ntop (AF_INET, &or->u.std.area_id, buf2,
691 BUFSIZ),
692 ospf_path_type_str[or->path_type],
693 or->cost);
694 for (pnode = listhead (or->path); pnode; nextnode (pnode))
695 {
696 path = getdata (pnode);
697 zlog_info (" -> %s", inet_ntoa (path->nexthop));
698 }
699 }
700 else
701 zlog_info ("R %s\t%s\t%s\t%d",
702 inet_ntop (AF_INET, &rn->p.u.prefix4, buf1, BUFSIZ),
703 inet_ntop (AF_INET, &or->u.std.area_id, buf2,
704 BUFSIZ),
705 ospf_path_type_str[or->path_type],
706 or->cost);
707 }
708 zlog_info ("========================================");
709}
710
711void
712ospf_terminate ()
713{
paul6d1fab62003-06-22 08:28:18 +0000714 struct ospf *ospf;
715 listnode node;
716
717 LIST_LOOP (om->ospf, ospf, node)
paul718e3742002-12-13 20:15:29 +0000718 {
paul6d1fab62003-06-22 08:28:18 +0000719 if (ospf->new_table)
720 ospf_route_delete (ospf->new_table);
721 if (ospf->old_external_route)
722 ospf_route_delete (ospf->old_external_route);
paul718e3742002-12-13 20:15:29 +0000723 }
724}
725
726/* This is 16.4.1 implementation.
727 o Intra-area paths using non-backbone areas are always the most preferred.
728 o The other paths, intra-area backbone paths and inter-area paths,
729 are of equal preference. */
730int
paul6d1fab62003-06-22 08:28:18 +0000731ospf_asbr_route_cmp (struct ospf *ospf, struct ospf_route *r1,
732 struct ospf_route *r2)
paul718e3742002-12-13 20:15:29 +0000733{
734 u_char r1_type, r2_type;
735
736 r1_type = r1->path_type;
737 r2_type = r2->path_type;
738
739 /* If RFC1583Compat flag is on -- all paths are equal. */
paul6d1fab62003-06-22 08:28:18 +0000740 if (CHECK_FLAG (ospf->config, OSPF_RFC1583_COMPATIBLE))
paul718e3742002-12-13 20:15:29 +0000741 return 0;
742
743 /* r1/r2 itself is backbone, and it's Inter-area path. */
744 if (OSPF_IS_AREA_ID_BACKBONE (r1->u.std.area_id))
745 r1_type = OSPF_PATH_INTER_AREA;
746 if (OSPF_IS_AREA_ID_BACKBONE (r2->u.std.area_id))
747 r2_type = OSPF_PATH_INTER_AREA;
748
749 return (r1_type - r2_type);
750}
751
752/* Compare two routes.
753 ret < 0 -- r1 is better.
754 ret == 0 -- r1 and r2 are the same.
755 ret > 0 -- r2 is better. */
756int
paul6d1fab62003-06-22 08:28:18 +0000757ospf_route_cmp (struct ospf *ospf, struct ospf_route *r1,
758 struct ospf_route *r2)
paul718e3742002-12-13 20:15:29 +0000759{
760 int ret = 0;
761
762 /* Path types of r1 and r2 are not the same. */
763 if ((ret = (r1->path_type - r2->path_type)))
764 return ret;
765
766 if (IS_DEBUG_OSPF_EVENT)
767 zlog_info ("Route[Compare]: Path types are the same.");
768 /* Path types are the same, compare any cost. */
769 switch (r1->path_type)
770 {
771 case OSPF_PATH_INTRA_AREA:
772 case OSPF_PATH_INTER_AREA:
773 break;
774 case OSPF_PATH_TYPE1_EXTERNAL:
paul6d1fab62003-06-22 08:28:18 +0000775 if (!CHECK_FLAG (ospf->config, OSPF_RFC1583_COMPATIBLE))
paul718e3742002-12-13 20:15:29 +0000776 {
paul6d1fab62003-06-22 08:28:18 +0000777 ret = ospf_asbr_route_cmp (ospf, r1->u.ext.asbr, r2->u.ext.asbr);
paul718e3742002-12-13 20:15:29 +0000778 if (ret != 0)
779 return ret;
780 }
781 break;
782 case OSPF_PATH_TYPE2_EXTERNAL:
783 if ((ret = (r1->u.ext.type2_cost - r2->u.ext.type2_cost)))
784 return ret;
785
paul6d1fab62003-06-22 08:28:18 +0000786 if (!CHECK_FLAG (ospf->config, OSPF_RFC1583_COMPATIBLE))
paul718e3742002-12-13 20:15:29 +0000787 {
paul6d1fab62003-06-22 08:28:18 +0000788 ret = ospf_asbr_route_cmp (ospf, r1->u.ext.asbr, r2->u.ext.asbr);
paul718e3742002-12-13 20:15:29 +0000789 if (ret != 0)
790 return ret;
791 }
792 break;
793 }
794
795 /* Anyway, compare the costs. */
796 return (r1->cost - r2->cost);
797}
798
799int
800ospf_path_exist (struct list *plist, struct in_addr nexthop,
801 struct ospf_interface *oi)
802{
803 listnode node;
804 struct ospf_path *path;
805
806 for (node = listhead (plist); node; nextnode (node))
807 {
808 path = node->data;
809
810 if (IPV4_ADDR_SAME (&path->nexthop, &nexthop) && path->oi == oi)
811 return 1;
812 }
813 return 0;
814}
815
816void
817ospf_route_copy_nexthops_from_vertex (struct ospf_route *to,
818 struct vertex *v)
819{
820 listnode nnode;
821 struct ospf_path *path;
822 struct vertex_nexthop *nexthop;
823
824 if (to->path == NULL)
825 to->path = list_new ();
826
827 for (nnode = listhead (v->nexthop); nnode; nextnode (nnode))
828 {
829 nexthop = getdata (nnode);
830
831 if (nexthop->oi != NULL)
832 {
833 if (! ospf_path_exist (to->path, nexthop->router, nexthop->oi))
834 {
835 path = ospf_path_new ();
836 path->nexthop = nexthop->router;
837 path->oi = nexthop->oi;
838 listnode_add (to->path, path);
839 }
840 }
841 }
842}
843
844struct ospf_path *
845ospf_path_lookup (list plist, struct ospf_path *path)
846{
847 listnode node;
848
849 for (node = listhead (plist); node; nextnode (node))
850 {
851 struct ospf_path *op = node->data;
852
853 if (IPV4_ADDR_SAME (&op->nexthop, &path->nexthop) &&
854 IPV4_ADDR_SAME (&op->adv_router, &path->adv_router))
855 return op;
856 }
857
858 return NULL;
859}
860
861void
862ospf_route_copy_nexthops (struct ospf_route *to, list from)
863{
864 listnode node;
865
866 if (to->path == NULL)
867 to->path = list_new ();
868
869 for (node = listhead (from); node; nextnode (node))
870 /* The same routes are just discarded. */
871 if (!ospf_path_lookup (to->path, node->data))
872 listnode_add (to->path, ospf_path_dup (node->data));
873}
874
875void
876ospf_route_subst_nexthops (struct ospf_route *to, list from)
877{
878 listnode node;
879 struct ospf_path *op;
880
881 for (node = listhead (to->path); node; nextnode (node))
882 if ((op = getdata (node)) != NULL)
883 {
884 ospf_path_free (op);
885 node->data = NULL;
886 }
887
888 list_delete_all_node (to->path);
889 ospf_route_copy_nexthops (to, from);
890}
891
892void
893ospf_route_subst (struct route_node *rn, struct ospf_route *new_or,
894 struct ospf_route *over)
895{
896 route_lock_node (rn);
897 ospf_route_free (rn->info);
898
899 ospf_route_copy_nexthops (new_or, over->path);
900 rn->info = new_or;
901 route_unlock_node (rn);
902}
903
904void
905ospf_route_add (struct route_table *rt, struct prefix_ipv4 *p,
906 struct ospf_route *new_or, struct ospf_route *over)
907{
908 struct route_node *rn;
909
910 rn = route_node_get (rt, (struct prefix *) p);
911
912 ospf_route_copy_nexthops (new_or, over->path);
913
914 if (rn->info)
915 {
916 if (IS_DEBUG_OSPF_EVENT)
917 zlog_info ("ospf_route_add(): something's wrong !");
918 route_unlock_node (rn);
919 return;
920 }
921
922 rn->info = new_or;
923}
924
925void
926ospf_prune_unreachable_networks (struct route_table *rt)
927{
928 struct route_node *rn, *next;
929 struct ospf_route *or;
930
931 if (IS_DEBUG_OSPF_EVENT)
932 zlog_info ("Pruning unreachable networks");
933
934 for (rn = route_top (rt); rn; rn = next)
935 {
936 next = route_next (rn);
937 if (rn->info != NULL)
938 {
939 or = rn->info;
940 if (listcount (or->path) == 0)
941 {
942 if (IS_DEBUG_OSPF_EVENT)
943 zlog_info ("Pruning route to %s/%d",
944 inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen);
945
946 ospf_route_free (or);
947 rn->info = NULL;
948 route_unlock_node (rn);
949 }
950 }
951 }
952}
953
954void
955ospf_prune_unreachable_routers (struct route_table *rtrs)
956{
957 struct route_node *rn, *next;
958 struct ospf_route *or;
959 listnode node, nnext;
960 list paths;
961
962 if (IS_DEBUG_OSPF_EVENT)
963 zlog_info ("Pruning unreachable routers");
964
965 for (rn = route_top (rtrs); rn; rn = next)
966 {
967 next = route_next (rn);
968 if ((paths = rn->info) == NULL)
969 continue;
970
971 for (node = listhead (paths); node; node = nnext)
972 {
973 nnext = node->next;
974
975 or = getdata (node);
976
977 if (listcount (or->path) == 0)
978 {
979 if (IS_DEBUG_OSPF_EVENT)
980 {
981 zlog_info ("Pruning route to rtr %s",
982 inet_ntoa (rn->p.u.prefix4));
983 zlog_info (" via area %s",
984 inet_ntoa (or->u.std.area_id));
985 }
986
987 listnode_delete (paths, or);
988 ospf_route_free (or);
989 }
990 }
991
992 if (listcount (paths) == 0)
993 {
994 if (IS_DEBUG_OSPF_EVENT)
995 zlog_info ("Pruning router node %s", inet_ntoa (rn->p.u.prefix4));
996
997 list_delete (paths);
998 rn->info = NULL;
999 route_unlock_node (rn);
1000 }
1001 }
1002}
1003
1004int
1005ospf_add_discard_route (struct route_table *rt, struct ospf_area *area,
1006 struct prefix_ipv4 *p)
1007{
1008 struct route_node *rn;
1009 struct ospf_route *or, *new_or;
1010
1011 rn = route_node_get (rt, (struct prefix *) p);
1012
1013 if (rn == NULL)
1014 {
1015 if (IS_DEBUG_OSPF_EVENT)
1016 zlog_info ("ospf_add_discard_route(): router installation error");
1017 return 0;
1018 }
1019
1020 if (rn->info) /* If the route to the same destination is found */
1021 {
1022 route_unlock_node (rn);
1023
1024 or = rn->info;
1025
1026 if (or->path_type == OSPF_PATH_INTRA_AREA)
1027 {
1028 if (IS_DEBUG_OSPF_EVENT)
1029 zlog_info ("ospf_add_discard_route(): "
1030 "an intra-area route exists");
1031 return 0;
1032 }
1033
1034 if (or->type == OSPF_DESTINATION_DISCARD)
1035 {
1036 if (IS_DEBUG_OSPF_EVENT)
1037 zlog_info ("ospf_add_discard_route(): "
1038 "discard entry already installed");
1039 return 0;
1040 }
1041
1042 ospf_route_free (rn->info);
1043 }
1044
1045 new_or = ospf_route_new ();
1046 new_or->type = OSPF_DESTINATION_DISCARD;
1047 new_or->id.s_addr = 0;
1048 new_or->cost = 0;
1049 new_or->u.std.area_id = area->area_id;
1050#ifdef HAVE_NSSA
1051 new_or->u.std.external_routing = area->external_routing;
1052#endif /* HAVE_NSSA */
1053 new_or->path_type = OSPF_PATH_INTER_AREA;
1054 rn->info = new_or;
1055
1056 ospf_zebra_add_discard (p);
1057
1058 return 1;
1059}
1060
1061void
1062ospf_delete_discard_route (struct prefix_ipv4 *p)
1063{
1064 ospf_zebra_delete_discard(p);
1065}
1066