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