blob: 9280767f22ec7108d3886a47b39f44366aa9001d [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;
hasso52dc7ee2004-09-23 19:18:23 +0000139 struct listnode *n1;
140 struct listnode *n2;
paul718e3742002-12-13 20:15:29 +0000141
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;
hasso52dc7ee2004-09-23 19:18:23 +0000282 struct listnode *nnode;
paul718e3742002-12-13 20:15:29 +0000283
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(): "
gdt630e4802004-08-31 17:28:41 +0000531 "another route to the same prefix found with cost %u",
532 cur_or->cost);
paul718e3742002-12-13 20:15:29 +0000533
534 /* Compare this distance to the current best cost to the stub
535 network. This is done by looking up the stub network's
536 current routing table entry. If the calculated distance D is
537 larger, go on to examine the next stub network link in the
538 LSA. */
539 if (cost > cur_or->cost)
540 {
541 if (IS_DEBUG_OSPF_EVENT)
542 zlog_info ("ospf_intra_add_stub(): old route is better, exit");
543 return;
544 }
545
546 /* (2) If this step is reached, the stub network's routing table
547 entry must be updated. Calculate the set of next hops that
548 would result from using the stub network link. This
549 calculation is shown in Section 16.1.1; input to this
550 calculation is the destination (the stub network) and the
551 parent vertex (the router vertex). If the distance D is the
552 same as the current routing table cost, simply add this set
553 of next hops to the routing table entry's list of next hops.
554 In this case, the routing table already has a Link State
555 Origin. If this Link State Origin is a router-LSA whose Link
556 State ID is smaller than V's Router ID, reset the Link State
557 Origin to V's router-LSA. */
558
559 if (cost == cur_or->cost)
560 {
561 if (IS_DEBUG_OSPF_EVENT)
562 zlog_info ("ospf_intra_add_stub(): routes are equal, merge");
563
564 ospf_route_copy_nexthops_from_vertex (cur_or, v);
565
566 if (IPV4_ADDR_CMP (&cur_or->u.std.origin->id, &lsa->header.id) < 0)
567 cur_or->u.std.origin = (struct lsa_header *) lsa;
568 return;
569 }
570
571 /* Otherwise D is smaller than the routing table cost.
572 Overwrite the current routing table entry by setting the
573 routing table entry's cost to D, and by setting the entry's
574 list of next hops to the newly calculated set. Set the
575 routing table entry's Link State Origin to V's router-LSA.
576 Then go on to examine the next stub network link. */
577
578 if (cost < cur_or->cost)
579 {
580 if (IS_DEBUG_OSPF_EVENT)
581 zlog_info ("ospf_intra_add_stub(): new route is better, set it");
582
583 cur_or->cost = cost;
584
paul048ba1d2003-08-15 16:04:21 +0000585 list_delete_all_node (cur_or->paths);
paul718e3742002-12-13 20:15:29 +0000586
587 ospf_route_copy_nexthops_from_vertex (cur_or, v);
588
589 cur_or->u.std.origin = (struct lsa_header *) lsa;
590 return;
591 }
592 }
593
594 if (IS_DEBUG_OSPF_EVENT)
595 zlog_info ("ospf_intra_add_stub(): installing new route");
596
597 or = ospf_route_new ();
598
599 or->id = v->id;
600 or->u.std.area_id = area->area_id;
paul718e3742002-12-13 20:15:29 +0000601 or->u.std.external_routing = area->external_routing;
paul718e3742002-12-13 20:15:29 +0000602 or->path_type = OSPF_PATH_INTRA_AREA;
603 or->cost = cost;
604 or->type = OSPF_DESTINATION_NETWORK;
605 or->u.std.origin = (struct lsa_header *) lsa;
paul718e3742002-12-13 20:15:29 +0000606
607 /* Nexthop is depend on connection type. */
608 if (v != area->spf)
609 {
610 if (IS_DEBUG_OSPF_EVENT)
611 zlog_info ("ospf_intra_add_stub(): this network is on remote router");
612 ospf_route_copy_nexthops_from_vertex (or, v);
613 }
614 else
615 {
616 if (IS_DEBUG_OSPF_EVENT)
617 zlog_info ("ospf_intra_add_stub(): this network is on this router");
618
paul6d1fab62003-06-22 08:28:18 +0000619 if ((oi = ospf_if_lookup_by_prefix (area->ospf, &p)))
paul718e3742002-12-13 20:15:29 +0000620 {
621 if (IS_DEBUG_OSPF_EVENT)
622 zlog_info ("ospf_intra_add_stub(): the interface is %s",
623 IF_NAME (oi));
624
625 path = ospf_path_new ();
626 path->nexthop.s_addr = 0;
627 path->oi = oi;
paul96735ee2003-08-10 02:51:22 +0000628 listnode_add (or->paths, path);
paul718e3742002-12-13 20:15:29 +0000629 }
630 else
631 {
632 if (IS_DEBUG_OSPF_EVENT)
633 zlog_info ("ospf_intra_add_stub(): where's the interface ?");
634 }
635 }
636
637 rn->info = or;
638
639 if (IS_DEBUG_OSPF_EVENT)
640 zlog_info("ospf_intra_add_stub(): Stop");
641}
642
643char *ospf_path_type_str[] =
644{
645 "unknown-type",
646 "intra-area",
647 "inter-area",
648 "type1-external",
649 "type2-external"
650};
651
652void
653ospf_route_table_dump (struct route_table *rt)
654{
655 struct route_node *rn;
656 struct ospf_route *or;
657 char buf1[BUFSIZ];
658 char buf2[BUFSIZ];
hasso52dc7ee2004-09-23 19:18:23 +0000659 struct listnode *pnode;
paul718e3742002-12-13 20:15:29 +0000660 struct ospf_path *path;
661
662#if 0
663 zlog_info ("Type Dest Area Path Type Cost Next Adv.");
664 zlog_info (" Hop(s) Router(s)");
665#endif /* 0 */
666
667 zlog_info ("========== OSPF routing table ==========");
668 for (rn = route_top (rt); rn; rn = route_next (rn))
669 if ((or = rn->info) != NULL)
670 {
671 if (or->type == OSPF_DESTINATION_NETWORK)
672 {
673 zlog_info ("N %s/%d\t%s\t%s\t%d",
674 inet_ntop (AF_INET, &rn->p.u.prefix4, buf1, BUFSIZ),
675 rn->p.prefixlen,
676 inet_ntop (AF_INET, &or->u.std.area_id, buf2,
677 BUFSIZ),
678 ospf_path_type_str[or->path_type],
679 or->cost);
paul96735ee2003-08-10 02:51:22 +0000680 for (pnode = listhead (or->paths); pnode; nextnode (pnode))
paul718e3742002-12-13 20:15:29 +0000681 {
682 path = getdata (pnode);
683 zlog_info (" -> %s", inet_ntoa (path->nexthop));
684 }
685 }
686 else
687 zlog_info ("R %s\t%s\t%s\t%d",
688 inet_ntop (AF_INET, &rn->p.u.prefix4, buf1, BUFSIZ),
689 inet_ntop (AF_INET, &or->u.std.area_id, buf2,
690 BUFSIZ),
691 ospf_path_type_str[or->path_type],
692 or->cost);
693 }
694 zlog_info ("========================================");
695}
696
697void
698ospf_terminate ()
699{
paul6d1fab62003-06-22 08:28:18 +0000700 struct ospf *ospf;
hasso52dc7ee2004-09-23 19:18:23 +0000701 struct listnode *node;
paul6d1fab62003-06-22 08:28:18 +0000702
703 LIST_LOOP (om->ospf, ospf, node)
paul718e3742002-12-13 20:15:29 +0000704 {
paul6d1fab62003-06-22 08:28:18 +0000705 if (ospf->new_table)
706 ospf_route_delete (ospf->new_table);
707 if (ospf->old_external_route)
708 ospf_route_delete (ospf->old_external_route);
paul718e3742002-12-13 20:15:29 +0000709 }
710}
711
712/* This is 16.4.1 implementation.
713 o Intra-area paths using non-backbone areas are always the most preferred.
714 o The other paths, intra-area backbone paths and inter-area paths,
715 are of equal preference. */
716int
paul6d1fab62003-06-22 08:28:18 +0000717ospf_asbr_route_cmp (struct ospf *ospf, struct ospf_route *r1,
718 struct ospf_route *r2)
paul718e3742002-12-13 20:15:29 +0000719{
720 u_char r1_type, r2_type;
721
722 r1_type = r1->path_type;
723 r2_type = r2->path_type;
724
725 /* If RFC1583Compat flag is on -- all paths are equal. */
paul6d1fab62003-06-22 08:28:18 +0000726 if (CHECK_FLAG (ospf->config, OSPF_RFC1583_COMPATIBLE))
paul718e3742002-12-13 20:15:29 +0000727 return 0;
728
729 /* r1/r2 itself is backbone, and it's Inter-area path. */
730 if (OSPF_IS_AREA_ID_BACKBONE (r1->u.std.area_id))
731 r1_type = OSPF_PATH_INTER_AREA;
732 if (OSPF_IS_AREA_ID_BACKBONE (r2->u.std.area_id))
733 r2_type = OSPF_PATH_INTER_AREA;
734
735 return (r1_type - r2_type);
736}
737
738/* Compare two routes.
739 ret < 0 -- r1 is better.
740 ret == 0 -- r1 and r2 are the same.
741 ret > 0 -- r2 is better. */
742int
paul6d1fab62003-06-22 08:28:18 +0000743ospf_route_cmp (struct ospf *ospf, struct ospf_route *r1,
744 struct ospf_route *r2)
paul718e3742002-12-13 20:15:29 +0000745{
746 int ret = 0;
747
748 /* Path types of r1 and r2 are not the same. */
749 if ((ret = (r1->path_type - r2->path_type)))
750 return ret;
751
752 if (IS_DEBUG_OSPF_EVENT)
753 zlog_info ("Route[Compare]: Path types are the same.");
754 /* Path types are the same, compare any cost. */
755 switch (r1->path_type)
756 {
757 case OSPF_PATH_INTRA_AREA:
758 case OSPF_PATH_INTER_AREA:
759 break;
760 case OSPF_PATH_TYPE1_EXTERNAL:
paul6d1fab62003-06-22 08:28:18 +0000761 if (!CHECK_FLAG (ospf->config, OSPF_RFC1583_COMPATIBLE))
paul718e3742002-12-13 20:15:29 +0000762 {
paul6d1fab62003-06-22 08:28:18 +0000763 ret = ospf_asbr_route_cmp (ospf, r1->u.ext.asbr, r2->u.ext.asbr);
paul718e3742002-12-13 20:15:29 +0000764 if (ret != 0)
765 return ret;
766 }
767 break;
768 case OSPF_PATH_TYPE2_EXTERNAL:
769 if ((ret = (r1->u.ext.type2_cost - r2->u.ext.type2_cost)))
770 return ret;
771
paul6d1fab62003-06-22 08:28:18 +0000772 if (!CHECK_FLAG (ospf->config, OSPF_RFC1583_COMPATIBLE))
paul718e3742002-12-13 20:15:29 +0000773 {
paul6d1fab62003-06-22 08:28:18 +0000774 ret = ospf_asbr_route_cmp (ospf, r1->u.ext.asbr, r2->u.ext.asbr);
paul718e3742002-12-13 20:15:29 +0000775 if (ret != 0)
776 return ret;
777 }
778 break;
779 }
780
781 /* Anyway, compare the costs. */
782 return (r1->cost - r2->cost);
783}
784
785int
786ospf_path_exist (struct list *plist, struct in_addr nexthop,
787 struct ospf_interface *oi)
788{
hasso52dc7ee2004-09-23 19:18:23 +0000789 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000790 struct ospf_path *path;
791
792 for (node = listhead (plist); node; nextnode (node))
793 {
794 path = node->data;
795
796 if (IPV4_ADDR_SAME (&path->nexthop, &nexthop) && path->oi == oi)
797 return 1;
798 }
799 return 0;
800}
801
802void
803ospf_route_copy_nexthops_from_vertex (struct ospf_route *to,
804 struct vertex *v)
805{
hasso52dc7ee2004-09-23 19:18:23 +0000806 struct listnode *nnode;
paul718e3742002-12-13 20:15:29 +0000807 struct ospf_path *path;
808 struct vertex_nexthop *nexthop;
809
paul96735ee2003-08-10 02:51:22 +0000810 assert (to->paths);
paul718e3742002-12-13 20:15:29 +0000811
812 for (nnode = listhead (v->nexthop); nnode; nextnode (nnode))
813 {
814 nexthop = getdata (nnode);
815
816 if (nexthop->oi != NULL)
817 {
paul96735ee2003-08-10 02:51:22 +0000818 if (! ospf_path_exist (to->paths, nexthop->router, nexthop->oi))
paul718e3742002-12-13 20:15:29 +0000819 {
820 path = ospf_path_new ();
821 path->nexthop = nexthop->router;
822 path->oi = nexthop->oi;
paul96735ee2003-08-10 02:51:22 +0000823 listnode_add (to->paths, path);
paul718e3742002-12-13 20:15:29 +0000824 }
825 }
826 }
827}
828
829struct ospf_path *
hasso52dc7ee2004-09-23 19:18:23 +0000830ospf_path_lookup (struct list *plist, struct ospf_path *path)
paul718e3742002-12-13 20:15:29 +0000831{
hasso52dc7ee2004-09-23 19:18:23 +0000832 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000833
834 for (node = listhead (plist); node; nextnode (node))
835 {
836 struct ospf_path *op = node->data;
837
838 if (IPV4_ADDR_SAME (&op->nexthop, &path->nexthop) &&
839 IPV4_ADDR_SAME (&op->adv_router, &path->adv_router))
840 return op;
841 }
842
843 return NULL;
844}
845
846void
hasso52dc7ee2004-09-23 19:18:23 +0000847ospf_route_copy_nexthops (struct ospf_route *to, struct list *from)
paul718e3742002-12-13 20:15:29 +0000848{
hasso52dc7ee2004-09-23 19:18:23 +0000849 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000850
paul96735ee2003-08-10 02:51:22 +0000851 assert (to->paths);
paul718e3742002-12-13 20:15:29 +0000852
853 for (node = listhead (from); node; nextnode (node))
854 /* The same routes are just discarded. */
paul96735ee2003-08-10 02:51:22 +0000855 if (!ospf_path_lookup (to->paths, node->data))
856 listnode_add (to->paths, ospf_path_dup (node->data));
paul718e3742002-12-13 20:15:29 +0000857}
858
859void
hasso52dc7ee2004-09-23 19:18:23 +0000860ospf_route_subst_nexthops (struct ospf_route *to, struct list *from)
paul718e3742002-12-13 20:15:29 +0000861{
paul718e3742002-12-13 20:15:29 +0000862
paul96735ee2003-08-10 02:51:22 +0000863 list_delete_all_node (to->paths);
paul718e3742002-12-13 20:15:29 +0000864 ospf_route_copy_nexthops (to, from);
865}
866
867void
868ospf_route_subst (struct route_node *rn, struct ospf_route *new_or,
869 struct ospf_route *over)
870{
871 route_lock_node (rn);
872 ospf_route_free (rn->info);
873
paul96735ee2003-08-10 02:51:22 +0000874 ospf_route_copy_nexthops (new_or, over->paths);
paul718e3742002-12-13 20:15:29 +0000875 rn->info = new_or;
876 route_unlock_node (rn);
877}
878
879void
880ospf_route_add (struct route_table *rt, struct prefix_ipv4 *p,
881 struct ospf_route *new_or, struct ospf_route *over)
882{
883 struct route_node *rn;
884
885 rn = route_node_get (rt, (struct prefix *) p);
886
paul96735ee2003-08-10 02:51:22 +0000887 ospf_route_copy_nexthops (new_or, over->paths);
paul718e3742002-12-13 20:15:29 +0000888
889 if (rn->info)
890 {
891 if (IS_DEBUG_OSPF_EVENT)
892 zlog_info ("ospf_route_add(): something's wrong !");
893 route_unlock_node (rn);
894 return;
895 }
896
897 rn->info = new_or;
898}
899
900void
901ospf_prune_unreachable_networks (struct route_table *rt)
902{
903 struct route_node *rn, *next;
904 struct ospf_route *or;
905
906 if (IS_DEBUG_OSPF_EVENT)
907 zlog_info ("Pruning unreachable networks");
908
909 for (rn = route_top (rt); rn; rn = next)
910 {
911 next = route_next (rn);
912 if (rn->info != NULL)
913 {
914 or = rn->info;
paul96735ee2003-08-10 02:51:22 +0000915 if (listcount (or->paths) == 0)
paul718e3742002-12-13 20:15:29 +0000916 {
917 if (IS_DEBUG_OSPF_EVENT)
918 zlog_info ("Pruning route to %s/%d",
919 inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen);
920
921 ospf_route_free (or);
922 rn->info = NULL;
923 route_unlock_node (rn);
924 }
925 }
926 }
927}
928
929void
930ospf_prune_unreachable_routers (struct route_table *rtrs)
931{
932 struct route_node *rn, *next;
933 struct ospf_route *or;
hasso52dc7ee2004-09-23 19:18:23 +0000934 struct listnode *node, *nnext;
935 struct list *paths;
paul718e3742002-12-13 20:15:29 +0000936
937 if (IS_DEBUG_OSPF_EVENT)
938 zlog_info ("Pruning unreachable routers");
939
940 for (rn = route_top (rtrs); rn; rn = next)
941 {
942 next = route_next (rn);
943 if ((paths = rn->info) == NULL)
944 continue;
945
946 for (node = listhead (paths); node; node = nnext)
947 {
948 nnext = node->next;
949
950 or = getdata (node);
951
paul96735ee2003-08-10 02:51:22 +0000952 if (listcount (or->paths) == 0)
paul718e3742002-12-13 20:15:29 +0000953 {
954 if (IS_DEBUG_OSPF_EVENT)
955 {
956 zlog_info ("Pruning route to rtr %s",
957 inet_ntoa (rn->p.u.prefix4));
958 zlog_info (" via area %s",
959 inet_ntoa (or->u.std.area_id));
960 }
961
962 listnode_delete (paths, or);
963 ospf_route_free (or);
964 }
965 }
966
967 if (listcount (paths) == 0)
968 {
969 if (IS_DEBUG_OSPF_EVENT)
970 zlog_info ("Pruning router node %s", inet_ntoa (rn->p.u.prefix4));
971
972 list_delete (paths);
973 rn->info = NULL;
974 route_unlock_node (rn);
975 }
976 }
977}
978
979int
980ospf_add_discard_route (struct route_table *rt, struct ospf_area *area,
981 struct prefix_ipv4 *p)
982{
983 struct route_node *rn;
984 struct ospf_route *or, *new_or;
985
986 rn = route_node_get (rt, (struct prefix *) p);
987
988 if (rn == NULL)
989 {
990 if (IS_DEBUG_OSPF_EVENT)
991 zlog_info ("ospf_add_discard_route(): router installation error");
992 return 0;
993 }
994
995 if (rn->info) /* If the route to the same destination is found */
996 {
997 route_unlock_node (rn);
998
999 or = rn->info;
1000
1001 if (or->path_type == OSPF_PATH_INTRA_AREA)
1002 {
1003 if (IS_DEBUG_OSPF_EVENT)
1004 zlog_info ("ospf_add_discard_route(): "
1005 "an intra-area route exists");
1006 return 0;
1007 }
1008
1009 if (or->type == OSPF_DESTINATION_DISCARD)
1010 {
1011 if (IS_DEBUG_OSPF_EVENT)
1012 zlog_info ("ospf_add_discard_route(): "
1013 "discard entry already installed");
1014 return 0;
1015 }
1016
1017 ospf_route_free (rn->info);
1018 }
1019
1020 new_or = ospf_route_new ();
1021 new_or->type = OSPF_DESTINATION_DISCARD;
1022 new_or->id.s_addr = 0;
1023 new_or->cost = 0;
1024 new_or->u.std.area_id = area->area_id;
paul718e3742002-12-13 20:15:29 +00001025 new_or->u.std.external_routing = area->external_routing;
paul718e3742002-12-13 20:15:29 +00001026 new_or->path_type = OSPF_PATH_INTER_AREA;
1027 rn->info = new_or;
1028
1029 ospf_zebra_add_discard (p);
1030
1031 return 1;
1032}
1033
1034void
1035ospf_delete_discard_route (struct prefix_ipv4 *p)
1036{
1037 ospf_zebra_delete_discard(p);
1038}
1039