blob: a8ee232f82a1ad3e4af9deb4385f230e3094a13b [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 {
hassofa2b17e2004-03-04 17:45:00 +0000195 struct prefix_ipv4 *p = (struct prefix_ipv4 *)(&rn->p);
196 if ( (ext_rn = route_node_lookup (external_routes, (struct prefix *)p)) )
paul6d1fab62003-06-22 08:28:18 +0000197 {
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;
paul718e3742002-12-13 20:15:29 +0000322 or->u.std.external_routing= area->external_routing;
paul718e3742002-12-13 20:15:29 +0000323 or->path_type = OSPF_PATH_INTRA_AREA;
324 or->cost = v->distance;
325
326 rn->info = or;
327}
328
329/* RFC2328 16.1. (4). For "router". */
330void
331ospf_intra_add_router (struct route_table *rt, struct vertex *v,
332 struct ospf_area *area)
333{
334 struct route_node *rn;
335 struct ospf_route *or;
336 struct prefix_ipv4 p;
337 struct router_lsa *lsa;
338
339 if (IS_DEBUG_OSPF_EVENT)
340 zlog_info ("ospf_intra_add_router: Start");
341
342 lsa = (struct router_lsa *) v->lsa;
343
344 if (IS_DEBUG_OSPF_EVENT)
345 zlog_info ("ospf_intra_add_router: LS ID: %s",
346 inet_ntoa (lsa->header.id));
347
348 ospf_vl_up_check (area, lsa->header.id, v);
349
350 if (!CHECK_FLAG (lsa->flags, ROUTER_LSA_SHORTCUT))
351 area->shortcut_capability = 0;
352
353 /* If the newly added vertex is an area border router or AS boundary
354 router, a routing table entry is added whose destination type is
355 "router". */
356 if (! IS_ROUTER_LSA_BORDER (lsa) && ! IS_ROUTER_LSA_EXTERNAL (lsa))
357 {
358 if (IS_DEBUG_OSPF_EVENT)
359 zlog_info ("ospf_intra_add_router: "
360 "this router is neither ASBR nor ABR, skipping it");
361 return;
362 }
363
364 /* Update ABR and ASBR count in this area. */
365 if (IS_ROUTER_LSA_BORDER (lsa))
366 area->abr_count++;
367 if (IS_ROUTER_LSA_EXTERNAL (lsa))
368 area->asbr_count++;
369
370 /* The Options field found in the associated router-LSA is copied
371 into the routing table entry's Optional capabilities field. Call
372 the newly added vertex Router X. */
373 or = ospf_route_new ();
374
375 or->id = v->id;
376 or->u.std.area_id = area->area_id;
paul718e3742002-12-13 20:15:29 +0000377 or->u.std.external_routing = area->external_routing;
paul718e3742002-12-13 20:15:29 +0000378 or->path_type = OSPF_PATH_INTRA_AREA;
379 or->cost = v->distance;
380 or->type = OSPF_DESTINATION_ROUTER;
381 or->u.std.origin = (struct lsa_header *) lsa;
382 or->u.std.options = lsa->header.options;
383 or->u.std.flags = lsa->flags;
384
385 /* If Router X is the endpoint of one of the calculating router's
386 virtual links, and the virtual link uses Area A as Transit area:
387 the virtual link is declared up, the IP address of the virtual
388 interface is set to the IP address of the outgoing interface
389 calculated above for Router X, and the virtual neighbor's IP
390 address is set to Router X's interface address (contained in
391 Router X's router-LSA) that points back to the root of the
392 shortest- path tree; equivalently, this is the interface that
393 points back to Router X's parent vertex on the shortest-path tree
394 (similar to the calculation in Section 16.1.1). */
395
396 p.family = AF_INET;
397 p.prefix = v->id;
398 p.prefixlen = IPV4_MAX_BITLEN;
399
400 if (IS_DEBUG_OSPF_EVENT)
401 zlog_info ("ospf_intra_add_router: talking about %s/%d",
402 inet_ntoa (p.prefix), p.prefixlen);
403
404 rn = route_node_get (rt, (struct prefix *) &p);
405
406 /* Note that we keep all routes to ABRs and ASBRs, not only the best */
407 if (rn->info == NULL)
408 rn->info = list_new ();
409 else
410 route_unlock_node (rn);
411
412 ospf_route_copy_nexthops_from_vertex (or, v);
413
414 listnode_add (rn->info, or);
415
hasso9e1be242004-04-20 03:50:59 +0000416 if (IS_DEBUG_OSPF_EVENT)
417 zlog_info ("ospf_intra_add_router: Stop");
paul718e3742002-12-13 20:15:29 +0000418}
419
420/* RFC2328 16.1. (4). For transit network. */
421void
422ospf_intra_add_transit (struct route_table *rt, struct vertex *v,
423 struct ospf_area *area)
424{
425 struct route_node *rn;
426 struct ospf_route *or;
427 struct prefix_ipv4 p;
428 struct network_lsa *lsa;
429
430 lsa = (struct network_lsa*) v->lsa;
431
432 /* If the newly added vertex is a transit network, the routing table
433 entry for the network is located. The entry's Destination ID is
434 the IP network number, which can be obtained by masking the
435 Vertex ID (Link State ID) with its associated subnet mask (found
436 in the body of the associated network-LSA). */
437 p.family = AF_INET;
438 p.prefix = v->id;
439 p.prefixlen = ip_masklen (lsa->mask);
440 apply_mask_ipv4 (&p);
441
442 rn = route_node_get (rt, (struct prefix *) &p);
443
444 /* If the routing table entry already exists (i.e., there is already
445 an intra-area route to the destination installed in the routing
446 table), multiple vertices have mapped to the same IP network.
447 For example, this can occur when a new Designated Router is being
448 established. In this case, the current routing table entry
449 should be overwritten if and only if the newly found path is just
450 as short and the current routing table entry's Link State Origin
451 has a smaller Link State ID than the newly added vertex' LSA. */
452 if (rn->info)
453 {
454 struct ospf_route *cur_or;
455
456 route_unlock_node (rn);
457 cur_or = rn->info;
458
459 if (v->distance > cur_or->cost ||
460 IPV4_ADDR_CMP (&cur_or->u.std.origin->id, &lsa->header.id) > 0)
461 return;
462
463 ospf_route_free (rn->info);
464 }
465
466 or = ospf_route_new ();
467
468 or->id = v->id;
469 or->u.std.area_id = area->area_id;
paul718e3742002-12-13 20:15:29 +0000470 or->u.std.external_routing = area->external_routing;
paul718e3742002-12-13 20:15:29 +0000471 or->path_type = OSPF_PATH_INTRA_AREA;
472 or->cost = v->distance;
473 or->type = OSPF_DESTINATION_NETWORK;
474 or->u.std.origin = (struct lsa_header *) lsa;
475
476 ospf_route_copy_nexthops_from_vertex (or, v);
477
478 rn->info = or;
479}
480
481/* RFC2328 16.1. second stage. */
482void
483ospf_intra_add_stub (struct route_table *rt, struct router_lsa_link *link,
484 struct vertex *v, struct ospf_area *area)
485{
486 u_int32_t cost;
487 struct route_node *rn;
488 struct ospf_route *or;
489 struct prefix_ipv4 p;
490 struct router_lsa *lsa;
491 struct ospf_interface *oi;
492 struct ospf_path *path;
493
494 if (IS_DEBUG_OSPF_EVENT)
495 zlog_info ("ospf_intra_add_stub(): Start");
496
497 lsa = (struct router_lsa *) v->lsa;
498
499 p.family = AF_INET;
500 p.prefix = link->link_id;
501 p.prefixlen = ip_masklen (link->link_data);
502 apply_mask_ipv4 (&p);
503
504 if (IS_DEBUG_OSPF_EVENT)
505 zlog_info ("ospf_intra_add_stub(): processing route to %s/%d",
506 inet_ntoa (p.prefix), p.prefixlen);
507
508 /* (1) Calculate the distance D of stub network from the root. D is
509 equal to the distance from the root to the router vertex
510 (calculated in stage 1), plus the stub network link's advertised
511 cost. */
512 cost = v->distance + ntohs (link->m[0].metric);
513
514 if (IS_DEBUG_OSPF_EVENT)
515 zlog_info ("ospf_intra_add_stub(): calculated cost is %d + %d = %d",
516 v->distance, ntohs(link->m[0].metric), cost);
517
518 rn = route_node_get (rt, (struct prefix *) &p);
519
520 /* Lookup current routing table. */
521 if (rn->info)
522 {
523 struct ospf_route *cur_or;
524
525 route_unlock_node (rn);
526
527 cur_or = rn->info;
528
529 if (IS_DEBUG_OSPF_EVENT)
530 zlog_info ("ospf_intra_add_stub(): "
531 "another route to the same prefix found");
532
533 /* Compare this distance to the current best cost to the stub
534 network. This is done by looking up the stub network's
535 current routing table entry. If the calculated distance D is
536 larger, go on to examine the next stub network link in the
537 LSA. */
538 if (cost > cur_or->cost)
539 {
540 if (IS_DEBUG_OSPF_EVENT)
541 zlog_info ("ospf_intra_add_stub(): old route is better, exit");
542 return;
543 }
544
545 /* (2) If this step is reached, the stub network's routing table
546 entry must be updated. Calculate the set of next hops that
547 would result from using the stub network link. This
548 calculation is shown in Section 16.1.1; input to this
549 calculation is the destination (the stub network) and the
550 parent vertex (the router vertex). If the distance D is the
551 same as the current routing table cost, simply add this set
552 of next hops to the routing table entry's list of next hops.
553 In this case, the routing table already has a Link State
554 Origin. If this Link State Origin is a router-LSA whose Link
555 State ID is smaller than V's Router ID, reset the Link State
556 Origin to V's router-LSA. */
557
558 if (cost == cur_or->cost)
559 {
560 if (IS_DEBUG_OSPF_EVENT)
561 zlog_info ("ospf_intra_add_stub(): routes are equal, merge");
562
563 ospf_route_copy_nexthops_from_vertex (cur_or, v);
564
565 if (IPV4_ADDR_CMP (&cur_or->u.std.origin->id, &lsa->header.id) < 0)
566 cur_or->u.std.origin = (struct lsa_header *) lsa;
567 return;
568 }
569
570 /* Otherwise D is smaller than the routing table cost.
571 Overwrite the current routing table entry by setting the
572 routing table entry's cost to D, and by setting the entry's
573 list of next hops to the newly calculated set. Set the
574 routing table entry's Link State Origin to V's router-LSA.
575 Then go on to examine the next stub network link. */
576
577 if (cost < cur_or->cost)
578 {
579 if (IS_DEBUG_OSPF_EVENT)
580 zlog_info ("ospf_intra_add_stub(): new route is better, set it");
581
582 cur_or->cost = cost;
583
paul048ba1d2003-08-15 16:04:21 +0000584 list_delete_all_node (cur_or->paths);
paul718e3742002-12-13 20:15:29 +0000585
586 ospf_route_copy_nexthops_from_vertex (cur_or, v);
587
588 cur_or->u.std.origin = (struct lsa_header *) lsa;
589 return;
590 }
591 }
592
593 if (IS_DEBUG_OSPF_EVENT)
594 zlog_info ("ospf_intra_add_stub(): installing new route");
595
596 or = ospf_route_new ();
597
598 or->id = v->id;
599 or->u.std.area_id = area->area_id;
paul718e3742002-12-13 20:15:29 +0000600 or->u.std.external_routing = area->external_routing;
paul718e3742002-12-13 20:15:29 +0000601 or->path_type = OSPF_PATH_INTRA_AREA;
602 or->cost = cost;
603 or->type = OSPF_DESTINATION_NETWORK;
604 or->u.std.origin = (struct lsa_header *) lsa;
paul718e3742002-12-13 20:15:29 +0000605
606 /* Nexthop is depend on connection type. */
607 if (v != area->spf)
608 {
609 if (IS_DEBUG_OSPF_EVENT)
610 zlog_info ("ospf_intra_add_stub(): this network is on remote router");
611 ospf_route_copy_nexthops_from_vertex (or, v);
612 }
613 else
614 {
615 if (IS_DEBUG_OSPF_EVENT)
616 zlog_info ("ospf_intra_add_stub(): this network is on this router");
617
paul6d1fab62003-06-22 08:28:18 +0000618 if ((oi = ospf_if_lookup_by_prefix (area->ospf, &p)))
paul718e3742002-12-13 20:15:29 +0000619 {
620 if (IS_DEBUG_OSPF_EVENT)
621 zlog_info ("ospf_intra_add_stub(): the interface is %s",
622 IF_NAME (oi));
623
624 path = ospf_path_new ();
625 path->nexthop.s_addr = 0;
626 path->oi = oi;
paul96735ee2003-08-10 02:51:22 +0000627 listnode_add (or->paths, path);
paul718e3742002-12-13 20:15:29 +0000628 }
629 else
630 {
631 if (IS_DEBUG_OSPF_EVENT)
632 zlog_info ("ospf_intra_add_stub(): where's the interface ?");
633 }
634 }
635
636 rn->info = or;
637
638 if (IS_DEBUG_OSPF_EVENT)
639 zlog_info("ospf_intra_add_stub(): Stop");
640}
641
642char *ospf_path_type_str[] =
643{
644 "unknown-type",
645 "intra-area",
646 "inter-area",
647 "type1-external",
648 "type2-external"
649};
650
651void
652ospf_route_table_dump (struct route_table *rt)
653{
654 struct route_node *rn;
655 struct ospf_route *or;
656 char buf1[BUFSIZ];
657 char buf2[BUFSIZ];
658 listnode pnode;
659 struct ospf_path *path;
660
661#if 0
662 zlog_info ("Type Dest Area Path Type Cost Next Adv.");
663 zlog_info (" Hop(s) Router(s)");
664#endif /* 0 */
665
666 zlog_info ("========== OSPF routing table ==========");
667 for (rn = route_top (rt); rn; rn = route_next (rn))
668 if ((or = rn->info) != NULL)
669 {
670 if (or->type == OSPF_DESTINATION_NETWORK)
671 {
672 zlog_info ("N %s/%d\t%s\t%s\t%d",
673 inet_ntop (AF_INET, &rn->p.u.prefix4, buf1, BUFSIZ),
674 rn->p.prefixlen,
675 inet_ntop (AF_INET, &or->u.std.area_id, buf2,
676 BUFSIZ),
677 ospf_path_type_str[or->path_type],
678 or->cost);
paul96735ee2003-08-10 02:51:22 +0000679 for (pnode = listhead (or->paths); pnode; nextnode (pnode))
paul718e3742002-12-13 20:15:29 +0000680 {
681 path = getdata (pnode);
682 zlog_info (" -> %s", inet_ntoa (path->nexthop));
683 }
684 }
685 else
686 zlog_info ("R %s\t%s\t%s\t%d",
687 inet_ntop (AF_INET, &rn->p.u.prefix4, buf1, BUFSIZ),
688 inet_ntop (AF_INET, &or->u.std.area_id, buf2,
689 BUFSIZ),
690 ospf_path_type_str[or->path_type],
691 or->cost);
692 }
693 zlog_info ("========================================");
694}
695
696void
697ospf_terminate ()
698{
paul6d1fab62003-06-22 08:28:18 +0000699 struct ospf *ospf;
700 listnode node;
701
702 LIST_LOOP (om->ospf, ospf, node)
paul718e3742002-12-13 20:15:29 +0000703 {
paul6d1fab62003-06-22 08:28:18 +0000704 if (ospf->new_table)
705 ospf_route_delete (ospf->new_table);
706 if (ospf->old_external_route)
707 ospf_route_delete (ospf->old_external_route);
paul718e3742002-12-13 20:15:29 +0000708 }
709}
710
711/* This is 16.4.1 implementation.
712 o Intra-area paths using non-backbone areas are always the most preferred.
713 o The other paths, intra-area backbone paths and inter-area paths,
714 are of equal preference. */
715int
paul6d1fab62003-06-22 08:28:18 +0000716ospf_asbr_route_cmp (struct ospf *ospf, struct ospf_route *r1,
717 struct ospf_route *r2)
paul718e3742002-12-13 20:15:29 +0000718{
719 u_char r1_type, r2_type;
720
721 r1_type = r1->path_type;
722 r2_type = r2->path_type;
723
724 /* If RFC1583Compat flag is on -- all paths are equal. */
paul6d1fab62003-06-22 08:28:18 +0000725 if (CHECK_FLAG (ospf->config, OSPF_RFC1583_COMPATIBLE))
paul718e3742002-12-13 20:15:29 +0000726 return 0;
727
728 /* r1/r2 itself is backbone, and it's Inter-area path. */
729 if (OSPF_IS_AREA_ID_BACKBONE (r1->u.std.area_id))
730 r1_type = OSPF_PATH_INTER_AREA;
731 if (OSPF_IS_AREA_ID_BACKBONE (r2->u.std.area_id))
732 r2_type = OSPF_PATH_INTER_AREA;
733
734 return (r1_type - r2_type);
735}
736
737/* Compare two routes.
738 ret < 0 -- r1 is better.
739 ret == 0 -- r1 and r2 are the same.
740 ret > 0 -- r2 is better. */
741int
paul6d1fab62003-06-22 08:28:18 +0000742ospf_route_cmp (struct ospf *ospf, struct ospf_route *r1,
743 struct ospf_route *r2)
paul718e3742002-12-13 20:15:29 +0000744{
745 int ret = 0;
746
747 /* Path types of r1 and r2 are not the same. */
748 if ((ret = (r1->path_type - r2->path_type)))
749 return ret;
750
751 if (IS_DEBUG_OSPF_EVENT)
752 zlog_info ("Route[Compare]: Path types are the same.");
753 /* Path types are the same, compare any cost. */
754 switch (r1->path_type)
755 {
756 case OSPF_PATH_INTRA_AREA:
757 case OSPF_PATH_INTER_AREA:
758 break;
759 case OSPF_PATH_TYPE1_EXTERNAL:
paul6d1fab62003-06-22 08:28:18 +0000760 if (!CHECK_FLAG (ospf->config, OSPF_RFC1583_COMPATIBLE))
paul718e3742002-12-13 20:15:29 +0000761 {
paul6d1fab62003-06-22 08:28:18 +0000762 ret = ospf_asbr_route_cmp (ospf, r1->u.ext.asbr, r2->u.ext.asbr);
paul718e3742002-12-13 20:15:29 +0000763 if (ret != 0)
764 return ret;
765 }
766 break;
767 case OSPF_PATH_TYPE2_EXTERNAL:
768 if ((ret = (r1->u.ext.type2_cost - r2->u.ext.type2_cost)))
769 return ret;
770
paul6d1fab62003-06-22 08:28:18 +0000771 if (!CHECK_FLAG (ospf->config, OSPF_RFC1583_COMPATIBLE))
paul718e3742002-12-13 20:15:29 +0000772 {
paul6d1fab62003-06-22 08:28:18 +0000773 ret = ospf_asbr_route_cmp (ospf, r1->u.ext.asbr, r2->u.ext.asbr);
paul718e3742002-12-13 20:15:29 +0000774 if (ret != 0)
775 return ret;
776 }
777 break;
778 }
779
780 /* Anyway, compare the costs. */
781 return (r1->cost - r2->cost);
782}
783
784int
785ospf_path_exist (struct list *plist, struct in_addr nexthop,
786 struct ospf_interface *oi)
787{
788 listnode node;
789 struct ospf_path *path;
790
791 for (node = listhead (plist); node; nextnode (node))
792 {
793 path = node->data;
794
795 if (IPV4_ADDR_SAME (&path->nexthop, &nexthop) && path->oi == oi)
796 return 1;
797 }
798 return 0;
799}
800
801void
802ospf_route_copy_nexthops_from_vertex (struct ospf_route *to,
803 struct vertex *v)
804{
805 listnode nnode;
806 struct ospf_path *path;
807 struct vertex_nexthop *nexthop;
808
paul96735ee2003-08-10 02:51:22 +0000809 assert (to->paths);
paul718e3742002-12-13 20:15:29 +0000810
811 for (nnode = listhead (v->nexthop); nnode; nextnode (nnode))
812 {
813 nexthop = getdata (nnode);
814
815 if (nexthop->oi != NULL)
816 {
paul96735ee2003-08-10 02:51:22 +0000817 if (! ospf_path_exist (to->paths, nexthop->router, nexthop->oi))
paul718e3742002-12-13 20:15:29 +0000818 {
819 path = ospf_path_new ();
820 path->nexthop = nexthop->router;
821 path->oi = nexthop->oi;
paul96735ee2003-08-10 02:51:22 +0000822 listnode_add (to->paths, path);
paul718e3742002-12-13 20:15:29 +0000823 }
824 }
825 }
826}
827
828struct ospf_path *
829ospf_path_lookup (list plist, struct ospf_path *path)
830{
831 listnode node;
832
833 for (node = listhead (plist); node; nextnode (node))
834 {
835 struct ospf_path *op = node->data;
836
837 if (IPV4_ADDR_SAME (&op->nexthop, &path->nexthop) &&
838 IPV4_ADDR_SAME (&op->adv_router, &path->adv_router))
839 return op;
840 }
841
842 return NULL;
843}
844
845void
846ospf_route_copy_nexthops (struct ospf_route *to, list from)
847{
848 listnode node;
849
paul96735ee2003-08-10 02:51:22 +0000850 assert (to->paths);
paul718e3742002-12-13 20:15:29 +0000851
852 for (node = listhead (from); node; nextnode (node))
853 /* The same routes are just discarded. */
paul96735ee2003-08-10 02:51:22 +0000854 if (!ospf_path_lookup (to->paths, node->data))
855 listnode_add (to->paths, ospf_path_dup (node->data));
paul718e3742002-12-13 20:15:29 +0000856}
857
858void
859ospf_route_subst_nexthops (struct ospf_route *to, list from)
860{
paul718e3742002-12-13 20:15:29 +0000861
paul96735ee2003-08-10 02:51:22 +0000862 list_delete_all_node (to->paths);
paul718e3742002-12-13 20:15:29 +0000863 ospf_route_copy_nexthops (to, from);
864}
865
866void
867ospf_route_subst (struct route_node *rn, struct ospf_route *new_or,
868 struct ospf_route *over)
869{
870 route_lock_node (rn);
871 ospf_route_free (rn->info);
872
paul96735ee2003-08-10 02:51:22 +0000873 ospf_route_copy_nexthops (new_or, over->paths);
paul718e3742002-12-13 20:15:29 +0000874 rn->info = new_or;
875 route_unlock_node (rn);
876}
877
878void
879ospf_route_add (struct route_table *rt, struct prefix_ipv4 *p,
880 struct ospf_route *new_or, struct ospf_route *over)
881{
882 struct route_node *rn;
883
884 rn = route_node_get (rt, (struct prefix *) p);
885
paul96735ee2003-08-10 02:51:22 +0000886 ospf_route_copy_nexthops (new_or, over->paths);
paul718e3742002-12-13 20:15:29 +0000887
888 if (rn->info)
889 {
890 if (IS_DEBUG_OSPF_EVENT)
891 zlog_info ("ospf_route_add(): something's wrong !");
892 route_unlock_node (rn);
893 return;
894 }
895
896 rn->info = new_or;
897}
898
899void
900ospf_prune_unreachable_networks (struct route_table *rt)
901{
902 struct route_node *rn, *next;
903 struct ospf_route *or;
904
905 if (IS_DEBUG_OSPF_EVENT)
906 zlog_info ("Pruning unreachable networks");
907
908 for (rn = route_top (rt); rn; rn = next)
909 {
910 next = route_next (rn);
911 if (rn->info != NULL)
912 {
913 or = rn->info;
paul96735ee2003-08-10 02:51:22 +0000914 if (listcount (or->paths) == 0)
paul718e3742002-12-13 20:15:29 +0000915 {
916 if (IS_DEBUG_OSPF_EVENT)
917 zlog_info ("Pruning route to %s/%d",
918 inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen);
919
920 ospf_route_free (or);
921 rn->info = NULL;
922 route_unlock_node (rn);
923 }
924 }
925 }
926}
927
928void
929ospf_prune_unreachable_routers (struct route_table *rtrs)
930{
931 struct route_node *rn, *next;
932 struct ospf_route *or;
933 listnode node, nnext;
934 list paths;
935
936 if (IS_DEBUG_OSPF_EVENT)
937 zlog_info ("Pruning unreachable routers");
938
939 for (rn = route_top (rtrs); rn; rn = next)
940 {
941 next = route_next (rn);
942 if ((paths = rn->info) == NULL)
943 continue;
944
945 for (node = listhead (paths); node; node = nnext)
946 {
947 nnext = node->next;
948
949 or = getdata (node);
950
paul96735ee2003-08-10 02:51:22 +0000951 if (listcount (or->paths) == 0)
paul718e3742002-12-13 20:15:29 +0000952 {
953 if (IS_DEBUG_OSPF_EVENT)
954 {
955 zlog_info ("Pruning route to rtr %s",
956 inet_ntoa (rn->p.u.prefix4));
957 zlog_info (" via area %s",
958 inet_ntoa (or->u.std.area_id));
959 }
960
961 listnode_delete (paths, or);
962 ospf_route_free (or);
963 }
964 }
965
966 if (listcount (paths) == 0)
967 {
968 if (IS_DEBUG_OSPF_EVENT)
969 zlog_info ("Pruning router node %s", inet_ntoa (rn->p.u.prefix4));
970
971 list_delete (paths);
972 rn->info = NULL;
973 route_unlock_node (rn);
974 }
975 }
976}
977
978int
979ospf_add_discard_route (struct route_table *rt, struct ospf_area *area,
980 struct prefix_ipv4 *p)
981{
982 struct route_node *rn;
983 struct ospf_route *or, *new_or;
984
985 rn = route_node_get (rt, (struct prefix *) p);
986
987 if (rn == NULL)
988 {
989 if (IS_DEBUG_OSPF_EVENT)
990 zlog_info ("ospf_add_discard_route(): router installation error");
991 return 0;
992 }
993
994 if (rn->info) /* If the route to the same destination is found */
995 {
996 route_unlock_node (rn);
997
998 or = rn->info;
999
1000 if (or->path_type == OSPF_PATH_INTRA_AREA)
1001 {
1002 if (IS_DEBUG_OSPF_EVENT)
1003 zlog_info ("ospf_add_discard_route(): "
1004 "an intra-area route exists");
1005 return 0;
1006 }
1007
1008 if (or->type == OSPF_DESTINATION_DISCARD)
1009 {
1010 if (IS_DEBUG_OSPF_EVENT)
1011 zlog_info ("ospf_add_discard_route(): "
1012 "discard entry already installed");
1013 return 0;
1014 }
1015
1016 ospf_route_free (rn->info);
1017 }
1018
1019 new_or = ospf_route_new ();
1020 new_or->type = OSPF_DESTINATION_DISCARD;
1021 new_or->id.s_addr = 0;
1022 new_or->cost = 0;
1023 new_or->u.std.area_id = area->area_id;
paul718e3742002-12-13 20:15:29 +00001024 new_or->u.std.external_routing = area->external_routing;
paul718e3742002-12-13 20:15:29 +00001025 new_or->path_type = OSPF_PATH_INTER_AREA;
1026 rn->info = new_or;
1027
1028 ospf_zebra_add_discard (p);
1029
1030 return 1;
1031}
1032
1033void
1034ospf_delete_discard_route (struct prefix_ipv4 *p)
1035{
1036 ospf_zebra_delete_discard(p);
1037}
1038