blob: 50fba75082163eb8f965c8b36c830d0ddd8902a9 [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
Paul Jakma2518efd2006-08-27 06:49:29 +000050 new->ctime = quagga_time (NULL);
paul718e3742002-12-13 20:15:29 +000051 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
paul4dadc292005-05-06 21:37:42 +000077static struct ospf_path *
paul718e3742002-12-13 20:15:29 +000078ospf_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);
paul1eb8ef22005-04-07 07:30:20 +0000161 n1 && n2; n1 = listnextnode (n1), n2 = listnextnode (n2))
paul718e3742002-12-13 20:15:29 +0000162 {
paul1eb8ef22005-04-07 07:30:20 +0000163 op = listgetdata (n1);
164 newop = listgetdata (n2);
paul718e3742002-12-13 20:15:29 +0000165
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 */
paul4dadc292005-05-06 21:37:42 +0000180static void
paul6d1fab62003-06-22 08:28:18 +0000181ospf_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 {
paul6d1fab62003-06-22 08:28:18 +0000198 if (ext_rn->info)
199 {
Paul Jakma894f8b62006-05-12 22:50:40 +0000200 ospf_zebra_delete (p, ext_rn->info);
paul6d1fab62003-06-22 08:28:18 +0000201 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 */
paul4dadc292005-05-06 21:37:42 +0000211static void
paul718e3742002-12-13 20:15:29 +0000212ospf_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
paul4dadc292005-05-06 21:37:42 +0000273static void
paul718e3742002-12-13 20:15:29 +0000274ospf_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;
pauleb3da6d2005-10-18 04:20:33 +0000281 struct vertex_parent *parent;
paul1eb8ef22005-04-07 07:30:20 +0000282 struct listnode *node, *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
pauleb3da6d2005-10-18 04:20:33 +0000309 for (ALL_LIST_ELEMENTS (v->parents, node, nnode, parent))
paul96735ee2003-08-10 02:51:22 +0000310 {
paul96735ee2003-08-10 02:51:22 +0000311 path = ospf_path_new ();
pauleb3da6d2005-10-18 04:20:33 +0000312 path->nexthop = parent->nexthop->router;
paul96735ee2003-08-10 02:51:22 +0000313 listnode_add (or->paths, path);
314 }
paul718e3742002-12-13 20:15:29 +0000315 }
316 else
317 or->type = OSPF_DESTINATION_ROUTER;
318
319 or->id = v->id;
320 or->u.std.area_id = area->area_id;
paul718e3742002-12-13 20:15:29 +0000321 or->u.std.external_routing= area->external_routing;
paul718e3742002-12-13 20:15:29 +0000322 or->path_type = OSPF_PATH_INTRA_AREA;
323 or->cost = v->distance;
324
325 rn->info = or;
326}
327
328/* RFC2328 16.1. (4). For "router". */
329void
330ospf_intra_add_router (struct route_table *rt, struct vertex *v,
331 struct ospf_area *area)
332{
333 struct route_node *rn;
334 struct ospf_route *or;
335 struct prefix_ipv4 p;
336 struct router_lsa *lsa;
337
338 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000339 zlog_debug ("ospf_intra_add_router: Start");
paul718e3742002-12-13 20:15:29 +0000340
341 lsa = (struct router_lsa *) v->lsa;
342
343 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000344 zlog_debug ("ospf_intra_add_router: LS ID: %s",
paul718e3742002-12-13 20:15:29 +0000345 inet_ntoa (lsa->header.id));
Paul Jakma9c27ef92006-05-04 07:32:57 +0000346
347 if (!OSPF_IS_AREA_BACKBONE(area))
348 ospf_vl_up_check (area, lsa->header.id, v);
paul718e3742002-12-13 20:15:29 +0000349
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)
ajs2a42e282004-12-08 18:43:03 +0000359 zlog_debug ("ospf_intra_add_router: "
paul718e3742002-12-13 20:15:29 +0000360 "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)
ajs2a42e282004-12-08 18:43:03 +0000401 zlog_debug ("ospf_intra_add_router: talking about %s/%d",
paul718e3742002-12-13 20:15:29 +0000402 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)
ajs2a42e282004-12-08 18:43:03 +0000417 zlog_debug ("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,
Paul Jakmab3bc68e2008-09-04 13:52:07 +0100484 struct vertex *v, struct ospf_area *area,
485 int parent_is_root)
paul718e3742002-12-13 20:15:29 +0000486{
487 u_int32_t cost;
488 struct route_node *rn;
489 struct ospf_route *or;
490 struct prefix_ipv4 p;
491 struct router_lsa *lsa;
492 struct ospf_interface *oi;
493 struct ospf_path *path;
494
495 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000496 zlog_debug ("ospf_intra_add_stub(): Start");
paul718e3742002-12-13 20:15:29 +0000497
498 lsa = (struct router_lsa *) v->lsa;
499
500 p.family = AF_INET;
501 p.prefix = link->link_id;
502 p.prefixlen = ip_masklen (link->link_data);
503 apply_mask_ipv4 (&p);
504
505 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000506 zlog_debug ("ospf_intra_add_stub(): processing route to %s/%d",
paul718e3742002-12-13 20:15:29 +0000507 inet_ntoa (p.prefix), p.prefixlen);
508
509 /* (1) Calculate the distance D of stub network from the root. D is
510 equal to the distance from the root to the router vertex
511 (calculated in stage 1), plus the stub network link's advertised
512 cost. */
513 cost = v->distance + ntohs (link->m[0].metric);
514
515 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000516 zlog_debug ("ospf_intra_add_stub(): calculated cost is %d + %d = %d",
paul718e3742002-12-13 20:15:29 +0000517 v->distance, ntohs(link->m[0].metric), cost);
Paul Jakmab3bc68e2008-09-04 13:52:07 +0100518
519 /* PtP links with /32 masks adds host routes to remote, directly
520 * connected hosts, see RFC 2328, 12.4.1.1, Option 1.
521 * Such routes can just be ignored for the sake of tidyness.
522 */
523 if (parent_is_root && link->link_data.s_addr == 0xffffffff &&
524 ospf_if_lookup_by_local_addr (area->ospf, NULL, link->link_id))
525 {
526 if (IS_DEBUG_OSPF_EVENT)
527 zlog_debug ("%s: ignoring host route %s/32 to self.",
528 __func__, inet_ntoa (link->link_id));
529 return;
530 }
531
paul718e3742002-12-13 20:15:29 +0000532 rn = route_node_get (rt, (struct prefix *) &p);
533
534 /* Lookup current routing table. */
535 if (rn->info)
536 {
537 struct ospf_route *cur_or;
538
539 route_unlock_node (rn);
540
541 cur_or = rn->info;
542
543 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000544 zlog_debug ("ospf_intra_add_stub(): "
gdt630e4802004-08-31 17:28:41 +0000545 "another route to the same prefix found with cost %u",
546 cur_or->cost);
paul718e3742002-12-13 20:15:29 +0000547
548 /* Compare this distance to the current best cost to the stub
549 network. This is done by looking up the stub network's
550 current routing table entry. If the calculated distance D is
551 larger, go on to examine the next stub network link in the
552 LSA. */
553 if (cost > cur_or->cost)
554 {
555 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000556 zlog_debug ("ospf_intra_add_stub(): old route is better, exit");
paul718e3742002-12-13 20:15:29 +0000557 return;
558 }
559
560 /* (2) If this step is reached, the stub network's routing table
561 entry must be updated. Calculate the set of next hops that
562 would result from using the stub network link. This
563 calculation is shown in Section 16.1.1; input to this
564 calculation is the destination (the stub network) and the
565 parent vertex (the router vertex). If the distance D is the
566 same as the current routing table cost, simply add this set
567 of next hops to the routing table entry's list of next hops.
568 In this case, the routing table already has a Link State
569 Origin. If this Link State Origin is a router-LSA whose Link
570 State ID is smaller than V's Router ID, reset the Link State
571 Origin to V's router-LSA. */
572
573 if (cost == cur_or->cost)
574 {
575 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000576 zlog_debug ("ospf_intra_add_stub(): routes are equal, merge");
paul718e3742002-12-13 20:15:29 +0000577
578 ospf_route_copy_nexthops_from_vertex (cur_or, v);
579
580 if (IPV4_ADDR_CMP (&cur_or->u.std.origin->id, &lsa->header.id) < 0)
581 cur_or->u.std.origin = (struct lsa_header *) lsa;
582 return;
583 }
584
585 /* Otherwise D is smaller than the routing table cost.
586 Overwrite the current routing table entry by setting the
587 routing table entry's cost to D, and by setting the entry's
588 list of next hops to the newly calculated set. Set the
589 routing table entry's Link State Origin to V's router-LSA.
590 Then go on to examine the next stub network link. */
591
592 if (cost < cur_or->cost)
593 {
594 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000595 zlog_debug ("ospf_intra_add_stub(): new route is better, set it");
paul718e3742002-12-13 20:15:29 +0000596
597 cur_or->cost = cost;
598
paul048ba1d2003-08-15 16:04:21 +0000599 list_delete_all_node (cur_or->paths);
paul718e3742002-12-13 20:15:29 +0000600
601 ospf_route_copy_nexthops_from_vertex (cur_or, v);
602
603 cur_or->u.std.origin = (struct lsa_header *) lsa;
604 return;
605 }
606 }
607
608 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000609 zlog_debug ("ospf_intra_add_stub(): installing new route");
paul718e3742002-12-13 20:15:29 +0000610
611 or = ospf_route_new ();
612
613 or->id = v->id;
614 or->u.std.area_id = area->area_id;
paul718e3742002-12-13 20:15:29 +0000615 or->u.std.external_routing = area->external_routing;
paul718e3742002-12-13 20:15:29 +0000616 or->path_type = OSPF_PATH_INTRA_AREA;
617 or->cost = cost;
618 or->type = OSPF_DESTINATION_NETWORK;
619 or->u.std.origin = (struct lsa_header *) lsa;
paul718e3742002-12-13 20:15:29 +0000620
621 /* Nexthop is depend on connection type. */
622 if (v != area->spf)
623 {
624 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000625 zlog_debug ("ospf_intra_add_stub(): this network is on remote router");
paul718e3742002-12-13 20:15:29 +0000626 ospf_route_copy_nexthops_from_vertex (or, v);
627 }
628 else
629 {
630 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000631 zlog_debug ("ospf_intra_add_stub(): this network is on this router");
paul718e3742002-12-13 20:15:29 +0000632
paul6d1fab62003-06-22 08:28:18 +0000633 if ((oi = ospf_if_lookup_by_prefix (area->ospf, &p)))
paul718e3742002-12-13 20:15:29 +0000634 {
635 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000636 zlog_debug ("ospf_intra_add_stub(): the interface is %s",
paul718e3742002-12-13 20:15:29 +0000637 IF_NAME (oi));
638
639 path = ospf_path_new ();
640 path->nexthop.s_addr = 0;
641 path->oi = oi;
paul96735ee2003-08-10 02:51:22 +0000642 listnode_add (or->paths, path);
paul718e3742002-12-13 20:15:29 +0000643 }
644 else
645 {
646 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000647 zlog_debug ("ospf_intra_add_stub(): where's the interface ?");
paul718e3742002-12-13 20:15:29 +0000648 }
649 }
650
651 rn->info = or;
652
653 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000654 zlog_debug("ospf_intra_add_stub(): Stop");
paul718e3742002-12-13 20:15:29 +0000655}
656
hassoeb1ce602004-10-08 08:17:22 +0000657const char *ospf_path_type_str[] =
paul718e3742002-12-13 20:15:29 +0000658{
659 "unknown-type",
660 "intra-area",
661 "inter-area",
662 "type1-external",
663 "type2-external"
664};
665
666void
667ospf_route_table_dump (struct route_table *rt)
668{
669 struct route_node *rn;
670 struct ospf_route *or;
671 char buf1[BUFSIZ];
672 char buf2[BUFSIZ];
hasso52dc7ee2004-09-23 19:18:23 +0000673 struct listnode *pnode;
paul718e3742002-12-13 20:15:29 +0000674 struct ospf_path *path;
675
676#if 0
ajs2a42e282004-12-08 18:43:03 +0000677 zlog_debug ("Type Dest Area Path Type Cost Next Adv.");
678 zlog_debug (" Hop(s) Router(s)");
paul718e3742002-12-13 20:15:29 +0000679#endif /* 0 */
680
ajs2a42e282004-12-08 18:43:03 +0000681 zlog_debug ("========== OSPF routing table ==========");
paul718e3742002-12-13 20:15:29 +0000682 for (rn = route_top (rt); rn; rn = route_next (rn))
683 if ((or = rn->info) != NULL)
684 {
685 if (or->type == OSPF_DESTINATION_NETWORK)
686 {
ajs2a42e282004-12-08 18:43:03 +0000687 zlog_debug ("N %s/%d\t%s\t%s\t%d",
paul718e3742002-12-13 20:15:29 +0000688 inet_ntop (AF_INET, &rn->p.u.prefix4, buf1, BUFSIZ),
689 rn->p.prefixlen,
690 inet_ntop (AF_INET, &or->u.std.area_id, buf2,
691 BUFSIZ),
692 ospf_path_type_str[or->path_type],
693 or->cost);
paul1eb8ef22005-04-07 07:30:20 +0000694 for (ALL_LIST_ELEMENTS_RO (or->paths, pnode, path))
695 zlog_debug (" -> %s", inet_ntoa (path->nexthop));
paul718e3742002-12-13 20:15:29 +0000696 }
697 else
ajs2a42e282004-12-08 18:43:03 +0000698 zlog_debug ("R %s\t%s\t%s\t%d",
paul718e3742002-12-13 20:15:29 +0000699 inet_ntop (AF_INET, &rn->p.u.prefix4, buf1, BUFSIZ),
700 inet_ntop (AF_INET, &or->u.std.area_id, buf2,
701 BUFSIZ),
702 ospf_path_type_str[or->path_type],
703 or->cost);
704 }
ajs2a42e282004-12-08 18:43:03 +0000705 zlog_debug ("========================================");
paul718e3742002-12-13 20:15:29 +0000706}
707
paul718e3742002-12-13 20:15:29 +0000708/* This is 16.4.1 implementation.
709 o Intra-area paths using non-backbone areas are always the most preferred.
710 o The other paths, intra-area backbone paths and inter-area paths,
711 are of equal preference. */
paul4dadc292005-05-06 21:37:42 +0000712static int
paul6d1fab62003-06-22 08:28:18 +0000713ospf_asbr_route_cmp (struct ospf *ospf, struct ospf_route *r1,
714 struct ospf_route *r2)
paul718e3742002-12-13 20:15:29 +0000715{
716 u_char r1_type, r2_type;
717
718 r1_type = r1->path_type;
719 r2_type = r2->path_type;
720
721 /* If RFC1583Compat flag is on -- all paths are equal. */
paul6d1fab62003-06-22 08:28:18 +0000722 if (CHECK_FLAG (ospf->config, OSPF_RFC1583_COMPATIBLE))
paul718e3742002-12-13 20:15:29 +0000723 return 0;
724
725 /* r1/r2 itself is backbone, and it's Inter-area path. */
726 if (OSPF_IS_AREA_ID_BACKBONE (r1->u.std.area_id))
727 r1_type = OSPF_PATH_INTER_AREA;
728 if (OSPF_IS_AREA_ID_BACKBONE (r2->u.std.area_id))
729 r2_type = OSPF_PATH_INTER_AREA;
730
731 return (r1_type - r2_type);
732}
733
734/* Compare two routes.
735 ret < 0 -- r1 is better.
736 ret == 0 -- r1 and r2 are the same.
737 ret > 0 -- r2 is better. */
738int
paul6d1fab62003-06-22 08:28:18 +0000739ospf_route_cmp (struct ospf *ospf, struct ospf_route *r1,
740 struct ospf_route *r2)
paul718e3742002-12-13 20:15:29 +0000741{
742 int ret = 0;
743
744 /* Path types of r1 and r2 are not the same. */
745 if ((ret = (r1->path_type - r2->path_type)))
746 return ret;
747
748 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000749 zlog_debug ("Route[Compare]: Path types are the same.");
paul718e3742002-12-13 20:15:29 +0000750 /* Path types are the same, compare any cost. */
751 switch (r1->path_type)
752 {
753 case OSPF_PATH_INTRA_AREA:
754 case OSPF_PATH_INTER_AREA:
755 break;
756 case OSPF_PATH_TYPE1_EXTERNAL:
paul6d1fab62003-06-22 08:28:18 +0000757 if (!CHECK_FLAG (ospf->config, OSPF_RFC1583_COMPATIBLE))
paul718e3742002-12-13 20:15:29 +0000758 {
paul6d1fab62003-06-22 08:28:18 +0000759 ret = ospf_asbr_route_cmp (ospf, r1->u.ext.asbr, r2->u.ext.asbr);
paul718e3742002-12-13 20:15:29 +0000760 if (ret != 0)
761 return ret;
762 }
763 break;
764 case OSPF_PATH_TYPE2_EXTERNAL:
765 if ((ret = (r1->u.ext.type2_cost - r2->u.ext.type2_cost)))
766 return ret;
767
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 }
776
777 /* Anyway, compare the costs. */
778 return (r1->cost - r2->cost);
779}
780
paul4dadc292005-05-06 21:37:42 +0000781static int
paul718e3742002-12-13 20:15:29 +0000782ospf_path_exist (struct list *plist, struct in_addr nexthop,
783 struct ospf_interface *oi)
784{
paul1eb8ef22005-04-07 07:30:20 +0000785 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000786 struct ospf_path *path;
787
paul1eb8ef22005-04-07 07:30:20 +0000788 for (ALL_LIST_ELEMENTS (plist, node, nnode, path))
789 if (IPV4_ADDR_SAME (&path->nexthop, &nexthop) && path->oi == oi)
790 return 1;
paul718e3742002-12-13 20:15:29 +0000791
paul718e3742002-12-13 20:15:29 +0000792 return 0;
793}
794
795void
796ospf_route_copy_nexthops_from_vertex (struct ospf_route *to,
797 struct vertex *v)
798{
paul1eb8ef22005-04-07 07:30:20 +0000799 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000800 struct ospf_path *path;
801 struct vertex_nexthop *nexthop;
pauleb3da6d2005-10-18 04:20:33 +0000802 struct vertex_parent *vp;
paul718e3742002-12-13 20:15:29 +0000803
paul96735ee2003-08-10 02:51:22 +0000804 assert (to->paths);
paul718e3742002-12-13 20:15:29 +0000805
pauleb3da6d2005-10-18 04:20:33 +0000806 for (ALL_LIST_ELEMENTS_RO (v->parents, node, vp))
paul718e3742002-12-13 20:15:29 +0000807 {
pauleb3da6d2005-10-18 04:20:33 +0000808 nexthop = vp->nexthop;
809
paul718e3742002-12-13 20:15:29 +0000810 if (nexthop->oi != NULL)
811 {
paul96735ee2003-08-10 02:51:22 +0000812 if (! ospf_path_exist (to->paths, nexthop->router, nexthop->oi))
paul718e3742002-12-13 20:15:29 +0000813 {
814 path = ospf_path_new ();
815 path->nexthop = nexthop->router;
816 path->oi = nexthop->oi;
paul96735ee2003-08-10 02:51:22 +0000817 listnode_add (to->paths, path);
paul718e3742002-12-13 20:15:29 +0000818 }
819 }
820 }
821}
822
823struct ospf_path *
hasso52dc7ee2004-09-23 19:18:23 +0000824ospf_path_lookup (struct list *plist, struct ospf_path *path)
paul718e3742002-12-13 20:15:29 +0000825{
hasso52dc7ee2004-09-23 19:18:23 +0000826 struct listnode *node;
paul1eb8ef22005-04-07 07:30:20 +0000827 struct ospf_path *op;
paul718e3742002-12-13 20:15:29 +0000828
paul1eb8ef22005-04-07 07:30:20 +0000829 for (ALL_LIST_ELEMENTS_RO (plist, node, op))
830 if (IPV4_ADDR_SAME (&op->nexthop, &path->nexthop) &&
831 IPV4_ADDR_SAME (&op->adv_router, &path->adv_router))
832 return op;
paul718e3742002-12-13 20:15:29 +0000833
834 return NULL;
835}
836
837void
hasso52dc7ee2004-09-23 19:18:23 +0000838ospf_route_copy_nexthops (struct ospf_route *to, struct list *from)
paul718e3742002-12-13 20:15:29 +0000839{
paul1eb8ef22005-04-07 07:30:20 +0000840 struct listnode *node, *nnode;
841 struct ospf_path *path;
paul718e3742002-12-13 20:15:29 +0000842
paul96735ee2003-08-10 02:51:22 +0000843 assert (to->paths);
paul718e3742002-12-13 20:15:29 +0000844
paul1eb8ef22005-04-07 07:30:20 +0000845 for (ALL_LIST_ELEMENTS (from, node, nnode, path))
paul718e3742002-12-13 20:15:29 +0000846 /* The same routes are just discarded. */
paul1eb8ef22005-04-07 07:30:20 +0000847 if (!ospf_path_lookup (to->paths, path))
848 listnode_add (to->paths, ospf_path_dup (path));
paul718e3742002-12-13 20:15:29 +0000849}
850
851void
hasso52dc7ee2004-09-23 19:18:23 +0000852ospf_route_subst_nexthops (struct ospf_route *to, struct list *from)
paul718e3742002-12-13 20:15:29 +0000853{
paul718e3742002-12-13 20:15:29 +0000854
paul96735ee2003-08-10 02:51:22 +0000855 list_delete_all_node (to->paths);
paul718e3742002-12-13 20:15:29 +0000856 ospf_route_copy_nexthops (to, from);
857}
858
859void
860ospf_route_subst (struct route_node *rn, struct ospf_route *new_or,
861 struct ospf_route *over)
862{
863 route_lock_node (rn);
864 ospf_route_free (rn->info);
865
paul96735ee2003-08-10 02:51:22 +0000866 ospf_route_copy_nexthops (new_or, over->paths);
paul718e3742002-12-13 20:15:29 +0000867 rn->info = new_or;
868 route_unlock_node (rn);
869}
870
871void
872ospf_route_add (struct route_table *rt, struct prefix_ipv4 *p,
873 struct ospf_route *new_or, struct ospf_route *over)
874{
875 struct route_node *rn;
876
877 rn = route_node_get (rt, (struct prefix *) p);
878
paul96735ee2003-08-10 02:51:22 +0000879 ospf_route_copy_nexthops (new_or, over->paths);
paul718e3742002-12-13 20:15:29 +0000880
881 if (rn->info)
882 {
883 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000884 zlog_debug ("ospf_route_add(): something's wrong !");
paul718e3742002-12-13 20:15:29 +0000885 route_unlock_node (rn);
886 return;
887 }
888
889 rn->info = new_or;
890}
891
892void
893ospf_prune_unreachable_networks (struct route_table *rt)
894{
895 struct route_node *rn, *next;
896 struct ospf_route *or;
897
898 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000899 zlog_debug ("Pruning unreachable networks");
paul718e3742002-12-13 20:15:29 +0000900
901 for (rn = route_top (rt); rn; rn = next)
902 {
903 next = route_next (rn);
904 if (rn->info != NULL)
905 {
906 or = rn->info;
paul96735ee2003-08-10 02:51:22 +0000907 if (listcount (or->paths) == 0)
paul718e3742002-12-13 20:15:29 +0000908 {
909 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000910 zlog_debug ("Pruning route to %s/%d",
paul718e3742002-12-13 20:15:29 +0000911 inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen);
912
913 ospf_route_free (or);
914 rn->info = NULL;
915 route_unlock_node (rn);
916 }
917 }
918 }
919}
920
921void
922ospf_prune_unreachable_routers (struct route_table *rtrs)
923{
924 struct route_node *rn, *next;
925 struct ospf_route *or;
paul1eb8ef22005-04-07 07:30:20 +0000926 struct listnode *node, *nnode;
hasso52dc7ee2004-09-23 19:18:23 +0000927 struct list *paths;
paul718e3742002-12-13 20:15:29 +0000928
929 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000930 zlog_debug ("Pruning unreachable routers");
paul718e3742002-12-13 20:15:29 +0000931
932 for (rn = route_top (rtrs); rn; rn = next)
933 {
934 next = route_next (rn);
935 if ((paths = rn->info) == NULL)
936 continue;
937
paul1eb8ef22005-04-07 07:30:20 +0000938 for (ALL_LIST_ELEMENTS (paths, node, nnode, or))
paul718e3742002-12-13 20:15:29 +0000939 {
paul96735ee2003-08-10 02:51:22 +0000940 if (listcount (or->paths) == 0)
paul718e3742002-12-13 20:15:29 +0000941 {
942 if (IS_DEBUG_OSPF_EVENT)
943 {
ajs2a42e282004-12-08 18:43:03 +0000944 zlog_debug ("Pruning route to rtr %s",
paul718e3742002-12-13 20:15:29 +0000945 inet_ntoa (rn->p.u.prefix4));
ajs2a42e282004-12-08 18:43:03 +0000946 zlog_debug (" via area %s",
paul718e3742002-12-13 20:15:29 +0000947 inet_ntoa (or->u.std.area_id));
948 }
949
950 listnode_delete (paths, or);
951 ospf_route_free (or);
952 }
953 }
954
955 if (listcount (paths) == 0)
956 {
957 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000958 zlog_debug ("Pruning router node %s", inet_ntoa (rn->p.u.prefix4));
paul718e3742002-12-13 20:15:29 +0000959
960 list_delete (paths);
961 rn->info = NULL;
962 route_unlock_node (rn);
963 }
964 }
965}
966
967int
968ospf_add_discard_route (struct route_table *rt, struct ospf_area *area,
969 struct prefix_ipv4 *p)
970{
971 struct route_node *rn;
972 struct ospf_route *or, *new_or;
973
974 rn = route_node_get (rt, (struct prefix *) p);
975
976 if (rn == NULL)
977 {
978 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000979 zlog_debug ("ospf_add_discard_route(): router installation error");
paul718e3742002-12-13 20:15:29 +0000980 return 0;
981 }
982
983 if (rn->info) /* If the route to the same destination is found */
984 {
985 route_unlock_node (rn);
986
987 or = rn->info;
988
989 if (or->path_type == OSPF_PATH_INTRA_AREA)
990 {
991 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000992 zlog_debug ("ospf_add_discard_route(): "
paul718e3742002-12-13 20:15:29 +0000993 "an intra-area route exists");
994 return 0;
995 }
996
997 if (or->type == OSPF_DESTINATION_DISCARD)
998 {
999 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001000 zlog_debug ("ospf_add_discard_route(): "
paul718e3742002-12-13 20:15:29 +00001001 "discard entry already installed");
1002 return 0;
1003 }
1004
1005 ospf_route_free (rn->info);
1006 }
1007
1008 new_or = ospf_route_new ();
1009 new_or->type = OSPF_DESTINATION_DISCARD;
1010 new_or->id.s_addr = 0;
1011 new_or->cost = 0;
1012 new_or->u.std.area_id = area->area_id;
paul718e3742002-12-13 20:15:29 +00001013 new_or->u.std.external_routing = area->external_routing;
paul718e3742002-12-13 20:15:29 +00001014 new_or->path_type = OSPF_PATH_INTER_AREA;
1015 rn->info = new_or;
1016
1017 ospf_zebra_add_discard (p);
1018
1019 return 1;
1020}
1021
1022void
1023ospf_delete_discard_route (struct prefix_ipv4 *p)
1024{
1025 ospf_zebra_delete_discard(p);
1026}
1027