blob: e1e1e390f84cd52f97b0e4f783ee1860b6c2d439 [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
paul96735ee2003-08-10 02:51:22 +0000589 list_delete (cur_or->paths);
590 cur_or->paths = NULL;
paul718e3742002-12-13 20:15:29 +0000591
592 ospf_route_copy_nexthops_from_vertex (cur_or, v);
593
594 cur_or->u.std.origin = (struct lsa_header *) lsa;
595 return;
596 }
597 }
598
599 if (IS_DEBUG_OSPF_EVENT)
600 zlog_info ("ospf_intra_add_stub(): installing new route");
601
602 or = ospf_route_new ();
603
604 or->id = v->id;
605 or->u.std.area_id = area->area_id;
606#ifdef HAVE_NSSA
607 or->u.std.external_routing = area->external_routing;
608#endif /* HAVE_NSSA */
609 or->path_type = OSPF_PATH_INTRA_AREA;
610 or->cost = cost;
611 or->type = OSPF_DESTINATION_NETWORK;
612 or->u.std.origin = (struct lsa_header *) lsa;
paul718e3742002-12-13 20:15:29 +0000613
614 /* Nexthop is depend on connection type. */
615 if (v != area->spf)
616 {
617 if (IS_DEBUG_OSPF_EVENT)
618 zlog_info ("ospf_intra_add_stub(): this network is on remote router");
619 ospf_route_copy_nexthops_from_vertex (or, v);
620 }
621 else
622 {
623 if (IS_DEBUG_OSPF_EVENT)
624 zlog_info ("ospf_intra_add_stub(): this network is on this router");
625
paul6d1fab62003-06-22 08:28:18 +0000626 if ((oi = ospf_if_lookup_by_prefix (area->ospf, &p)))
paul718e3742002-12-13 20:15:29 +0000627 {
628 if (IS_DEBUG_OSPF_EVENT)
629 zlog_info ("ospf_intra_add_stub(): the interface is %s",
630 IF_NAME (oi));
631
632 path = ospf_path_new ();
633 path->nexthop.s_addr = 0;
634 path->oi = oi;
paul96735ee2003-08-10 02:51:22 +0000635 listnode_add (or->paths, path);
paul718e3742002-12-13 20:15:29 +0000636 }
637 else
638 {
639 if (IS_DEBUG_OSPF_EVENT)
640 zlog_info ("ospf_intra_add_stub(): where's the interface ?");
641 }
642 }
643
644 rn->info = or;
645
646 if (IS_DEBUG_OSPF_EVENT)
647 zlog_info("ospf_intra_add_stub(): Stop");
648}
649
650char *ospf_path_type_str[] =
651{
652 "unknown-type",
653 "intra-area",
654 "inter-area",
655 "type1-external",
656 "type2-external"
657};
658
659void
660ospf_route_table_dump (struct route_table *rt)
661{
662 struct route_node *rn;
663 struct ospf_route *or;
664 char buf1[BUFSIZ];
665 char buf2[BUFSIZ];
666 listnode pnode;
667 struct ospf_path *path;
668
669#if 0
670 zlog_info ("Type Dest Area Path Type Cost Next Adv.");
671 zlog_info (" Hop(s) Router(s)");
672#endif /* 0 */
673
674 zlog_info ("========== OSPF routing table ==========");
675 for (rn = route_top (rt); rn; rn = route_next (rn))
676 if ((or = rn->info) != NULL)
677 {
678 if (or->type == OSPF_DESTINATION_NETWORK)
679 {
680 zlog_info ("N %s/%d\t%s\t%s\t%d",
681 inet_ntop (AF_INET, &rn->p.u.prefix4, buf1, BUFSIZ),
682 rn->p.prefixlen,
683 inet_ntop (AF_INET, &or->u.std.area_id, buf2,
684 BUFSIZ),
685 ospf_path_type_str[or->path_type],
686 or->cost);
paul96735ee2003-08-10 02:51:22 +0000687 for (pnode = listhead (or->paths); pnode; nextnode (pnode))
paul718e3742002-12-13 20:15:29 +0000688 {
689 path = getdata (pnode);
690 zlog_info (" -> %s", inet_ntoa (path->nexthop));
691 }
692 }
693 else
694 zlog_info ("R %s\t%s\t%s\t%d",
695 inet_ntop (AF_INET, &rn->p.u.prefix4, buf1, BUFSIZ),
696 inet_ntop (AF_INET, &or->u.std.area_id, buf2,
697 BUFSIZ),
698 ospf_path_type_str[or->path_type],
699 or->cost);
700 }
701 zlog_info ("========================================");
702}
703
704void
705ospf_terminate ()
706{
paul6d1fab62003-06-22 08:28:18 +0000707 struct ospf *ospf;
708 listnode node;
709
710 LIST_LOOP (om->ospf, ospf, node)
paul718e3742002-12-13 20:15:29 +0000711 {
paul6d1fab62003-06-22 08:28:18 +0000712 if (ospf->new_table)
713 ospf_route_delete (ospf->new_table);
714 if (ospf->old_external_route)
715 ospf_route_delete (ospf->old_external_route);
paul718e3742002-12-13 20:15:29 +0000716 }
717}
718
719/* This is 16.4.1 implementation.
720 o Intra-area paths using non-backbone areas are always the most preferred.
721 o The other paths, intra-area backbone paths and inter-area paths,
722 are of equal preference. */
723int
paul6d1fab62003-06-22 08:28:18 +0000724ospf_asbr_route_cmp (struct ospf *ospf, struct ospf_route *r1,
725 struct ospf_route *r2)
paul718e3742002-12-13 20:15:29 +0000726{
727 u_char r1_type, r2_type;
728
729 r1_type = r1->path_type;
730 r2_type = r2->path_type;
731
732 /* If RFC1583Compat flag is on -- all paths are equal. */
paul6d1fab62003-06-22 08:28:18 +0000733 if (CHECK_FLAG (ospf->config, OSPF_RFC1583_COMPATIBLE))
paul718e3742002-12-13 20:15:29 +0000734 return 0;
735
736 /* r1/r2 itself is backbone, and it's Inter-area path. */
737 if (OSPF_IS_AREA_ID_BACKBONE (r1->u.std.area_id))
738 r1_type = OSPF_PATH_INTER_AREA;
739 if (OSPF_IS_AREA_ID_BACKBONE (r2->u.std.area_id))
740 r2_type = OSPF_PATH_INTER_AREA;
741
742 return (r1_type - r2_type);
743}
744
745/* Compare two routes.
746 ret < 0 -- r1 is better.
747 ret == 0 -- r1 and r2 are the same.
748 ret > 0 -- r2 is better. */
749int
paul6d1fab62003-06-22 08:28:18 +0000750ospf_route_cmp (struct ospf *ospf, struct ospf_route *r1,
751 struct ospf_route *r2)
paul718e3742002-12-13 20:15:29 +0000752{
753 int ret = 0;
754
755 /* Path types of r1 and r2 are not the same. */
756 if ((ret = (r1->path_type - r2->path_type)))
757 return ret;
758
759 if (IS_DEBUG_OSPF_EVENT)
760 zlog_info ("Route[Compare]: Path types are the same.");
761 /* Path types are the same, compare any cost. */
762 switch (r1->path_type)
763 {
764 case OSPF_PATH_INTRA_AREA:
765 case OSPF_PATH_INTER_AREA:
766 break;
767 case OSPF_PATH_TYPE1_EXTERNAL:
paul6d1fab62003-06-22 08:28:18 +0000768 if (!CHECK_FLAG (ospf->config, OSPF_RFC1583_COMPATIBLE))
paul718e3742002-12-13 20:15:29 +0000769 {
paul6d1fab62003-06-22 08:28:18 +0000770 ret = ospf_asbr_route_cmp (ospf, r1->u.ext.asbr, r2->u.ext.asbr);
paul718e3742002-12-13 20:15:29 +0000771 if (ret != 0)
772 return ret;
773 }
774 break;
775 case OSPF_PATH_TYPE2_EXTERNAL:
776 if ((ret = (r1->u.ext.type2_cost - r2->u.ext.type2_cost)))
777 return ret;
778
paul6d1fab62003-06-22 08:28:18 +0000779 if (!CHECK_FLAG (ospf->config, OSPF_RFC1583_COMPATIBLE))
paul718e3742002-12-13 20:15:29 +0000780 {
paul6d1fab62003-06-22 08:28:18 +0000781 ret = ospf_asbr_route_cmp (ospf, r1->u.ext.asbr, r2->u.ext.asbr);
paul718e3742002-12-13 20:15:29 +0000782 if (ret != 0)
783 return ret;
784 }
785 break;
786 }
787
788 /* Anyway, compare the costs. */
789 return (r1->cost - r2->cost);
790}
791
792int
793ospf_path_exist (struct list *plist, struct in_addr nexthop,
794 struct ospf_interface *oi)
795{
796 listnode node;
797 struct ospf_path *path;
798
799 for (node = listhead (plist); node; nextnode (node))
800 {
801 path = node->data;
802
803 if (IPV4_ADDR_SAME (&path->nexthop, &nexthop) && path->oi == oi)
804 return 1;
805 }
806 return 0;
807}
808
809void
810ospf_route_copy_nexthops_from_vertex (struct ospf_route *to,
811 struct vertex *v)
812{
813 listnode nnode;
814 struct ospf_path *path;
815 struct vertex_nexthop *nexthop;
816
paul96735ee2003-08-10 02:51:22 +0000817 assert (to->paths);
paul718e3742002-12-13 20:15:29 +0000818
819 for (nnode = listhead (v->nexthop); nnode; nextnode (nnode))
820 {
821 nexthop = getdata (nnode);
822
823 if (nexthop->oi != NULL)
824 {
paul96735ee2003-08-10 02:51:22 +0000825 if (! ospf_path_exist (to->paths, nexthop->router, nexthop->oi))
paul718e3742002-12-13 20:15:29 +0000826 {
827 path = ospf_path_new ();
828 path->nexthop = nexthop->router;
829 path->oi = nexthop->oi;
paul96735ee2003-08-10 02:51:22 +0000830 listnode_add (to->paths, path);
paul718e3742002-12-13 20:15:29 +0000831 }
832 }
833 }
834}
835
836struct ospf_path *
837ospf_path_lookup (list plist, struct ospf_path *path)
838{
839 listnode node;
840
841 for (node = listhead (plist); node; nextnode (node))
842 {
843 struct ospf_path *op = node->data;
844
845 if (IPV4_ADDR_SAME (&op->nexthop, &path->nexthop) &&
846 IPV4_ADDR_SAME (&op->adv_router, &path->adv_router))
847 return op;
848 }
849
850 return NULL;
851}
852
853void
854ospf_route_copy_nexthops (struct ospf_route *to, list from)
855{
856 listnode node;
857
paul96735ee2003-08-10 02:51:22 +0000858 assert (to->paths);
paul718e3742002-12-13 20:15:29 +0000859
860 for (node = listhead (from); node; nextnode (node))
861 /* The same routes are just discarded. */
paul96735ee2003-08-10 02:51:22 +0000862 if (!ospf_path_lookup (to->paths, node->data))
863 listnode_add (to->paths, ospf_path_dup (node->data));
paul718e3742002-12-13 20:15:29 +0000864}
865
866void
867ospf_route_subst_nexthops (struct ospf_route *to, list from)
868{
paul718e3742002-12-13 20:15:29 +0000869
paul96735ee2003-08-10 02:51:22 +0000870 list_delete_all_node (to->paths);
paul718e3742002-12-13 20:15:29 +0000871 ospf_route_copy_nexthops (to, from);
872}
873
874void
875ospf_route_subst (struct route_node *rn, struct ospf_route *new_or,
876 struct ospf_route *over)
877{
878 route_lock_node (rn);
879 ospf_route_free (rn->info);
880
paul96735ee2003-08-10 02:51:22 +0000881 ospf_route_copy_nexthops (new_or, over->paths);
paul718e3742002-12-13 20:15:29 +0000882 rn->info = new_or;
883 route_unlock_node (rn);
884}
885
886void
887ospf_route_add (struct route_table *rt, struct prefix_ipv4 *p,
888 struct ospf_route *new_or, struct ospf_route *over)
889{
890 struct route_node *rn;
891
892 rn = route_node_get (rt, (struct prefix *) p);
893
paul96735ee2003-08-10 02:51:22 +0000894 ospf_route_copy_nexthops (new_or, over->paths);
paul718e3742002-12-13 20:15:29 +0000895
896 if (rn->info)
897 {
898 if (IS_DEBUG_OSPF_EVENT)
899 zlog_info ("ospf_route_add(): something's wrong !");
900 route_unlock_node (rn);
901 return;
902 }
903
904 rn->info = new_or;
905}
906
907void
908ospf_prune_unreachable_networks (struct route_table *rt)
909{
910 struct route_node *rn, *next;
911 struct ospf_route *or;
912
913 if (IS_DEBUG_OSPF_EVENT)
914 zlog_info ("Pruning unreachable networks");
915
916 for (rn = route_top (rt); rn; rn = next)
917 {
918 next = route_next (rn);
919 if (rn->info != NULL)
920 {
921 or = rn->info;
paul96735ee2003-08-10 02:51:22 +0000922 if (listcount (or->paths) == 0)
paul718e3742002-12-13 20:15:29 +0000923 {
924 if (IS_DEBUG_OSPF_EVENT)
925 zlog_info ("Pruning route to %s/%d",
926 inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen);
927
928 ospf_route_free (or);
929 rn->info = NULL;
930 route_unlock_node (rn);
931 }
932 }
933 }
934}
935
936void
937ospf_prune_unreachable_routers (struct route_table *rtrs)
938{
939 struct route_node *rn, *next;
940 struct ospf_route *or;
941 listnode node, nnext;
942 list paths;
943
944 if (IS_DEBUG_OSPF_EVENT)
945 zlog_info ("Pruning unreachable routers");
946
947 for (rn = route_top (rtrs); rn; rn = next)
948 {
949 next = route_next (rn);
950 if ((paths = rn->info) == NULL)
951 continue;
952
953 for (node = listhead (paths); node; node = nnext)
954 {
955 nnext = node->next;
956
957 or = getdata (node);
958
paul96735ee2003-08-10 02:51:22 +0000959 if (listcount (or->paths) == 0)
paul718e3742002-12-13 20:15:29 +0000960 {
961 if (IS_DEBUG_OSPF_EVENT)
962 {
963 zlog_info ("Pruning route to rtr %s",
964 inet_ntoa (rn->p.u.prefix4));
965 zlog_info (" via area %s",
966 inet_ntoa (or->u.std.area_id));
967 }
968
969 listnode_delete (paths, or);
970 ospf_route_free (or);
971 }
972 }
973
974 if (listcount (paths) == 0)
975 {
976 if (IS_DEBUG_OSPF_EVENT)
977 zlog_info ("Pruning router node %s", inet_ntoa (rn->p.u.prefix4));
978
979 list_delete (paths);
980 rn->info = NULL;
981 route_unlock_node (rn);
982 }
983 }
984}
985
986int
987ospf_add_discard_route (struct route_table *rt, struct ospf_area *area,
988 struct prefix_ipv4 *p)
989{
990 struct route_node *rn;
991 struct ospf_route *or, *new_or;
992
993 rn = route_node_get (rt, (struct prefix *) p);
994
995 if (rn == NULL)
996 {
997 if (IS_DEBUG_OSPF_EVENT)
998 zlog_info ("ospf_add_discard_route(): router installation error");
999 return 0;
1000 }
1001
1002 if (rn->info) /* If the route to the same destination is found */
1003 {
1004 route_unlock_node (rn);
1005
1006 or = rn->info;
1007
1008 if (or->path_type == OSPF_PATH_INTRA_AREA)
1009 {
1010 if (IS_DEBUG_OSPF_EVENT)
1011 zlog_info ("ospf_add_discard_route(): "
1012 "an intra-area route exists");
1013 return 0;
1014 }
1015
1016 if (or->type == OSPF_DESTINATION_DISCARD)
1017 {
1018 if (IS_DEBUG_OSPF_EVENT)
1019 zlog_info ("ospf_add_discard_route(): "
1020 "discard entry already installed");
1021 return 0;
1022 }
1023
1024 ospf_route_free (rn->info);
1025 }
1026
1027 new_or = ospf_route_new ();
1028 new_or->type = OSPF_DESTINATION_DISCARD;
1029 new_or->id.s_addr = 0;
1030 new_or->cost = 0;
1031 new_or->u.std.area_id = area->area_id;
1032#ifdef HAVE_NSSA
1033 new_or->u.std.external_routing = area->external_routing;
1034#endif /* HAVE_NSSA */
1035 new_or->path_type = OSPF_PATH_INTER_AREA;
1036 rn->info = new_or;
1037
1038 ospf_zebra_add_discard (p);
1039
1040 return 1;
1041}
1042
1043void
1044ospf_delete_discard_route (struct prefix_ipv4 *p)
1045{
1046 ospf_zebra_delete_discard(p);
1047}
1048