blob: 0829e8ea010649330d63b56331085bf1d3e8b7bb [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;
Joakim Tjernlund77a1c4e2009-02-01 11:12:11 +0100168 if (op->oi->ifp->ifindex != newop->oi->ifp->ifindex)
169 return 0;
paul718e3742002-12-13 20:15:29 +0000170 }
171 return 1;
172 }
173 else if (prefix_same (&rn->p, (struct prefix *) prefix))
174 return 1;
175 }
176 return 0;
177}
178
paul6d1fab62003-06-22 08:28:18 +0000179/* delete routes generated from AS-External routes if there is a inter/intra
180 * area route
181 */
paul4dadc292005-05-06 21:37:42 +0000182static void
paul6d1fab62003-06-22 08:28:18 +0000183ospf_route_delete_same_ext(struct route_table *external_routes,
184 struct route_table *routes)
185{
186 struct route_node *rn,
187 *ext_rn;
188
189 if ( (external_routes == NULL) || (routes == NULL) )
190 return;
191
192 /* Remove deleted routes */
193 for ( rn = route_top (routes); rn; rn = route_next (rn) )
194 {
195 if (rn && rn->info)
196 {
hassofa2b17e2004-03-04 17:45:00 +0000197 struct prefix_ipv4 *p = (struct prefix_ipv4 *)(&rn->p);
198 if ( (ext_rn = route_node_lookup (external_routes, (struct prefix *)p)) )
paul6d1fab62003-06-22 08:28:18 +0000199 {
paul6d1fab62003-06-22 08:28:18 +0000200 if (ext_rn->info)
201 {
Paul Jakma894f8b62006-05-12 22:50:40 +0000202 ospf_zebra_delete (p, ext_rn->info);
paul6d1fab62003-06-22 08:28:18 +0000203 ospf_route_free( ext_rn->info);
204 ext_rn->info = NULL;
205 }
206 route_unlock_node (ext_rn);
207 }
208 }
209 }
210}
211
paul718e3742002-12-13 20:15:29 +0000212/* rt: Old, cmprt: New */
paul4dadc292005-05-06 21:37:42 +0000213static void
paul718e3742002-12-13 20:15:29 +0000214ospf_route_delete_uniq (struct route_table *rt, struct route_table *cmprt)
215{
216 struct route_node *rn;
217 struct ospf_route *or;
218
219 for (rn = route_top (rt); rn; rn = route_next (rn))
220 if ((or = rn->info) != NULL)
221 if (or->path_type == OSPF_PATH_INTRA_AREA ||
222 or->path_type == OSPF_PATH_INTER_AREA)
223 {
224 if (or->type == OSPF_DESTINATION_NETWORK)
225 {
226 if (! ospf_route_match_same (cmprt,
227 (struct prefix_ipv4 *) &rn->p, or))
228 ospf_zebra_delete ((struct prefix_ipv4 *) &rn->p, or);
229 }
230 else if (or->type == OSPF_DESTINATION_DISCARD)
231 if (! ospf_route_match_same (cmprt,
232 (struct prefix_ipv4 *) &rn->p, or))
233 ospf_zebra_delete_discard ((struct prefix_ipv4 *) &rn->p);
234 }
235}
236
237/* Install routes to table. */
238void
paul6d1fab62003-06-22 08:28:18 +0000239ospf_route_install (struct ospf *ospf, struct route_table *rt)
paul718e3742002-12-13 20:15:29 +0000240{
241 struct route_node *rn;
242 struct ospf_route *or;
243
244 /* rt contains new routing table, new_table contains an old one.
245 updating pointers */
paul6d1fab62003-06-22 08:28:18 +0000246 if (ospf->old_table)
247 ospf_route_table_free (ospf->old_table);
248
249 ospf->old_table = ospf->new_table;
250 ospf->new_table = rt;
paul718e3742002-12-13 20:15:29 +0000251
252 /* Delete old routes. */
paul6d1fab62003-06-22 08:28:18 +0000253 if (ospf->old_table)
254 ospf_route_delete_uniq (ospf->old_table, rt);
255 if (ospf->old_external_route)
256 ospf_route_delete_same_ext (ospf->old_external_route, rt);
paul718e3742002-12-13 20:15:29 +0000257
258 /* Install new routes. */
259 for (rn = route_top (rt); rn; rn = route_next (rn))
260 if ((or = rn->info) != NULL)
261 {
262 if (or->type == OSPF_DESTINATION_NETWORK)
263 {
paul6d1fab62003-06-22 08:28:18 +0000264 if (! ospf_route_match_same (ospf->old_table,
paul718e3742002-12-13 20:15:29 +0000265 (struct prefix_ipv4 *)&rn->p, or))
266 ospf_zebra_add ((struct prefix_ipv4 *) &rn->p, or);
267 }
268 else if (or->type == OSPF_DESTINATION_DISCARD)
paul6d1fab62003-06-22 08:28:18 +0000269 if (! ospf_route_match_same (ospf->old_table,
paul718e3742002-12-13 20:15:29 +0000270 (struct prefix_ipv4 *) &rn->p, or))
271 ospf_zebra_add_discard ((struct prefix_ipv4 *) &rn->p);
272 }
273}
274
paul4dadc292005-05-06 21:37:42 +0000275static void
paul718e3742002-12-13 20:15:29 +0000276ospf_intra_route_add (struct route_table *rt, struct vertex *v,
277 struct ospf_area *area)
278{
279 struct route_node *rn;
280 struct ospf_route *or;
281 struct prefix_ipv4 p;
282 struct ospf_path *path;
pauleb3da6d2005-10-18 04:20:33 +0000283 struct vertex_parent *parent;
paul1eb8ef22005-04-07 07:30:20 +0000284 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000285
286 p.family = AF_INET;
287 p.prefix = v->id;
288 if (v->type == OSPF_VERTEX_ROUTER)
289 p.prefixlen = IPV4_MAX_BITLEN;
290 else
291 {
292 struct network_lsa *lsa = (struct network_lsa *) v->lsa;
293 p.prefixlen = ip_masklen (lsa->mask);
294 }
295 apply_mask_ipv4 (&p);
296
297 rn = route_node_get (rt, (struct prefix *) &p);
298 if (rn->info)
299 {
300 zlog_warn ("Same routing information exists for %s", inet_ntoa (v->id));
301 route_unlock_node (rn);
302 return;
303 }
304
305 or = ospf_route_new ();
306
307 if (v->type == OSPF_VERTEX_NETWORK)
308 {
309 or->type = OSPF_DESTINATION_NETWORK;
paul718e3742002-12-13 20:15:29 +0000310
pauleb3da6d2005-10-18 04:20:33 +0000311 for (ALL_LIST_ELEMENTS (v->parents, node, nnode, parent))
paul96735ee2003-08-10 02:51:22 +0000312 {
paul96735ee2003-08-10 02:51:22 +0000313 path = ospf_path_new ();
pauleb3da6d2005-10-18 04:20:33 +0000314 path->nexthop = parent->nexthop->router;
paul96735ee2003-08-10 02:51:22 +0000315 listnode_add (or->paths, path);
316 }
paul718e3742002-12-13 20:15:29 +0000317 }
318 else
319 or->type = OSPF_DESTINATION_ROUTER;
320
321 or->id = v->id;
322 or->u.std.area_id = area->area_id;
paul718e3742002-12-13 20:15:29 +0000323 or->u.std.external_routing= area->external_routing;
paul718e3742002-12-13 20:15:29 +0000324 or->path_type = OSPF_PATH_INTRA_AREA;
325 or->cost = v->distance;
326
327 rn->info = or;
328}
329
330/* RFC2328 16.1. (4). For "router". */
331void
332ospf_intra_add_router (struct route_table *rt, struct vertex *v,
333 struct ospf_area *area)
334{
335 struct route_node *rn;
336 struct ospf_route *or;
337 struct prefix_ipv4 p;
338 struct router_lsa *lsa;
339
340 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000341 zlog_debug ("ospf_intra_add_router: Start");
paul718e3742002-12-13 20:15:29 +0000342
343 lsa = (struct router_lsa *) v->lsa;
344
345 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000346 zlog_debug ("ospf_intra_add_router: LS ID: %s",
paul718e3742002-12-13 20:15:29 +0000347 inet_ntoa (lsa->header.id));
Paul Jakma9c27ef92006-05-04 07:32:57 +0000348
349 if (!OSPF_IS_AREA_BACKBONE(area))
350 ospf_vl_up_check (area, lsa->header.id, v);
paul718e3742002-12-13 20:15:29 +0000351
352 if (!CHECK_FLAG (lsa->flags, ROUTER_LSA_SHORTCUT))
353 area->shortcut_capability = 0;
354
355 /* If the newly added vertex is an area border router or AS boundary
356 router, a routing table entry is added whose destination type is
357 "router". */
358 if (! IS_ROUTER_LSA_BORDER (lsa) && ! IS_ROUTER_LSA_EXTERNAL (lsa))
359 {
360 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000361 zlog_debug ("ospf_intra_add_router: "
paul718e3742002-12-13 20:15:29 +0000362 "this router is neither ASBR nor ABR, skipping it");
363 return;
364 }
365
366 /* Update ABR and ASBR count in this area. */
367 if (IS_ROUTER_LSA_BORDER (lsa))
368 area->abr_count++;
369 if (IS_ROUTER_LSA_EXTERNAL (lsa))
370 area->asbr_count++;
371
372 /* The Options field found in the associated router-LSA is copied
373 into the routing table entry's Optional capabilities field. Call
374 the newly added vertex Router X. */
375 or = ospf_route_new ();
376
377 or->id = v->id;
378 or->u.std.area_id = area->area_id;
paul718e3742002-12-13 20:15:29 +0000379 or->u.std.external_routing = area->external_routing;
paul718e3742002-12-13 20:15:29 +0000380 or->path_type = OSPF_PATH_INTRA_AREA;
381 or->cost = v->distance;
382 or->type = OSPF_DESTINATION_ROUTER;
383 or->u.std.origin = (struct lsa_header *) lsa;
384 or->u.std.options = lsa->header.options;
385 or->u.std.flags = lsa->flags;
386
387 /* If Router X is the endpoint of one of the calculating router's
388 virtual links, and the virtual link uses Area A as Transit area:
389 the virtual link is declared up, the IP address of the virtual
390 interface is set to the IP address of the outgoing interface
391 calculated above for Router X, and the virtual neighbor's IP
392 address is set to Router X's interface address (contained in
393 Router X's router-LSA) that points back to the root of the
394 shortest- path tree; equivalently, this is the interface that
395 points back to Router X's parent vertex on the shortest-path tree
396 (similar to the calculation in Section 16.1.1). */
397
398 p.family = AF_INET;
399 p.prefix = v->id;
400 p.prefixlen = IPV4_MAX_BITLEN;
401
402 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000403 zlog_debug ("ospf_intra_add_router: talking about %s/%d",
paul718e3742002-12-13 20:15:29 +0000404 inet_ntoa (p.prefix), p.prefixlen);
405
406 rn = route_node_get (rt, (struct prefix *) &p);
407
408 /* Note that we keep all routes to ABRs and ASBRs, not only the best */
409 if (rn->info == NULL)
410 rn->info = list_new ();
411 else
412 route_unlock_node (rn);
413
414 ospf_route_copy_nexthops_from_vertex (or, v);
415
416 listnode_add (rn->info, or);
417
hasso9e1be242004-04-20 03:50:59 +0000418 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000419 zlog_debug ("ospf_intra_add_router: Stop");
paul718e3742002-12-13 20:15:29 +0000420}
421
422/* RFC2328 16.1. (4). For transit network. */
423void
424ospf_intra_add_transit (struct route_table *rt, struct vertex *v,
425 struct ospf_area *area)
426{
427 struct route_node *rn;
428 struct ospf_route *or;
429 struct prefix_ipv4 p;
430 struct network_lsa *lsa;
431
432 lsa = (struct network_lsa*) v->lsa;
433
434 /* If the newly added vertex is a transit network, the routing table
435 entry for the network is located. The entry's Destination ID is
436 the IP network number, which can be obtained by masking the
437 Vertex ID (Link State ID) with its associated subnet mask (found
438 in the body of the associated network-LSA). */
439 p.family = AF_INET;
440 p.prefix = v->id;
441 p.prefixlen = ip_masklen (lsa->mask);
442 apply_mask_ipv4 (&p);
443
444 rn = route_node_get (rt, (struct prefix *) &p);
445
446 /* If the routing table entry already exists (i.e., there is already
447 an intra-area route to the destination installed in the routing
448 table), multiple vertices have mapped to the same IP network.
449 For example, this can occur when a new Designated Router is being
450 established. In this case, the current routing table entry
451 should be overwritten if and only if the newly found path is just
452 as short and the current routing table entry's Link State Origin
453 has a smaller Link State ID than the newly added vertex' LSA. */
454 if (rn->info)
455 {
456 struct ospf_route *cur_or;
457
458 route_unlock_node (rn);
459 cur_or = rn->info;
460
461 if (v->distance > cur_or->cost ||
462 IPV4_ADDR_CMP (&cur_or->u.std.origin->id, &lsa->header.id) > 0)
463 return;
464
465 ospf_route_free (rn->info);
466 }
467
468 or = ospf_route_new ();
469
470 or->id = v->id;
471 or->u.std.area_id = area->area_id;
paul718e3742002-12-13 20:15:29 +0000472 or->u.std.external_routing = area->external_routing;
paul718e3742002-12-13 20:15:29 +0000473 or->path_type = OSPF_PATH_INTRA_AREA;
474 or->cost = v->distance;
475 or->type = OSPF_DESTINATION_NETWORK;
476 or->u.std.origin = (struct lsa_header *) lsa;
477
478 ospf_route_copy_nexthops_from_vertex (or, v);
479
480 rn->info = or;
481}
482
483/* RFC2328 16.1. second stage. */
484void
485ospf_intra_add_stub (struct route_table *rt, struct router_lsa_link *link,
Paul Jakmab3bc68e2008-09-04 13:52:07 +0100486 struct vertex *v, struct ospf_area *area,
487 int parent_is_root)
paul718e3742002-12-13 20:15:29 +0000488{
489 u_int32_t cost;
490 struct route_node *rn;
491 struct ospf_route *or;
492 struct prefix_ipv4 p;
493 struct router_lsa *lsa;
494 struct ospf_interface *oi;
495 struct ospf_path *path;
496
497 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000498 zlog_debug ("ospf_intra_add_stub(): Start");
paul718e3742002-12-13 20:15:29 +0000499
500 lsa = (struct router_lsa *) v->lsa;
501
502 p.family = AF_INET;
503 p.prefix = link->link_id;
504 p.prefixlen = ip_masklen (link->link_data);
505 apply_mask_ipv4 (&p);
506
507 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000508 zlog_debug ("ospf_intra_add_stub(): processing route to %s/%d",
paul718e3742002-12-13 20:15:29 +0000509 inet_ntoa (p.prefix), p.prefixlen);
510
511 /* (1) Calculate the distance D of stub network from the root. D is
512 equal to the distance from the root to the router vertex
513 (calculated in stage 1), plus the stub network link's advertised
514 cost. */
515 cost = v->distance + ntohs (link->m[0].metric);
516
517 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000518 zlog_debug ("ospf_intra_add_stub(): calculated cost is %d + %d = %d",
paul718e3742002-12-13 20:15:29 +0000519 v->distance, ntohs(link->m[0].metric), cost);
Paul Jakmab3bc68e2008-09-04 13:52:07 +0100520
521 /* PtP links with /32 masks adds host routes to remote, directly
522 * connected hosts, see RFC 2328, 12.4.1.1, Option 1.
523 * Such routes can just be ignored for the sake of tidyness.
524 */
525 if (parent_is_root && link->link_data.s_addr == 0xffffffff &&
526 ospf_if_lookup_by_local_addr (area->ospf, NULL, link->link_id))
527 {
528 if (IS_DEBUG_OSPF_EVENT)
529 zlog_debug ("%s: ignoring host route %s/32 to self.",
530 __func__, inet_ntoa (link->link_id));
531 return;
532 }
533
paul718e3742002-12-13 20:15:29 +0000534 rn = route_node_get (rt, (struct prefix *) &p);
535
536 /* Lookup current routing table. */
537 if (rn->info)
538 {
539 struct ospf_route *cur_or;
540
541 route_unlock_node (rn);
542
543 cur_or = rn->info;
544
545 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000546 zlog_debug ("ospf_intra_add_stub(): "
gdt630e4802004-08-31 17:28:41 +0000547 "another route to the same prefix found with cost %u",
548 cur_or->cost);
paul718e3742002-12-13 20:15:29 +0000549
550 /* Compare this distance to the current best cost to the stub
551 network. This is done by looking up the stub network's
552 current routing table entry. If the calculated distance D is
553 larger, go on to examine the next stub network link in the
554 LSA. */
555 if (cost > cur_or->cost)
556 {
557 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000558 zlog_debug ("ospf_intra_add_stub(): old route is better, exit");
paul718e3742002-12-13 20:15:29 +0000559 return;
560 }
561
562 /* (2) If this step is reached, the stub network's routing table
563 entry must be updated. Calculate the set of next hops that
564 would result from using the stub network link. This
565 calculation is shown in Section 16.1.1; input to this
566 calculation is the destination (the stub network) and the
567 parent vertex (the router vertex). If the distance D is the
568 same as the current routing table cost, simply add this set
569 of next hops to the routing table entry's list of next hops.
570 In this case, the routing table already has a Link State
571 Origin. If this Link State Origin is a router-LSA whose Link
572 State ID is smaller than V's Router ID, reset the Link State
573 Origin to V's router-LSA. */
574
575 if (cost == cur_or->cost)
576 {
577 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000578 zlog_debug ("ospf_intra_add_stub(): routes are equal, merge");
paul718e3742002-12-13 20:15:29 +0000579
580 ospf_route_copy_nexthops_from_vertex (cur_or, v);
581
582 if (IPV4_ADDR_CMP (&cur_or->u.std.origin->id, &lsa->header.id) < 0)
583 cur_or->u.std.origin = (struct lsa_header *) lsa;
584 return;
585 }
586
587 /* Otherwise D is smaller than the routing table cost.
588 Overwrite the current routing table entry by setting the
589 routing table entry's cost to D, and by setting the entry's
590 list of next hops to the newly calculated set. Set the
591 routing table entry's Link State Origin to V's router-LSA.
592 Then go on to examine the next stub network link. */
593
594 if (cost < cur_or->cost)
595 {
596 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000597 zlog_debug ("ospf_intra_add_stub(): new route is better, set it");
paul718e3742002-12-13 20:15:29 +0000598
599 cur_or->cost = cost;
600
paul048ba1d2003-08-15 16:04:21 +0000601 list_delete_all_node (cur_or->paths);
paul718e3742002-12-13 20:15:29 +0000602
603 ospf_route_copy_nexthops_from_vertex (cur_or, v);
604
605 cur_or->u.std.origin = (struct lsa_header *) lsa;
606 return;
607 }
608 }
609
610 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000611 zlog_debug ("ospf_intra_add_stub(): installing new route");
paul718e3742002-12-13 20:15:29 +0000612
613 or = ospf_route_new ();
614
615 or->id = v->id;
616 or->u.std.area_id = area->area_id;
paul718e3742002-12-13 20:15:29 +0000617 or->u.std.external_routing = area->external_routing;
paul718e3742002-12-13 20:15:29 +0000618 or->path_type = OSPF_PATH_INTRA_AREA;
619 or->cost = cost;
620 or->type = OSPF_DESTINATION_NETWORK;
621 or->u.std.origin = (struct lsa_header *) lsa;
paul718e3742002-12-13 20:15:29 +0000622
623 /* Nexthop is depend on connection type. */
624 if (v != area->spf)
625 {
626 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000627 zlog_debug ("ospf_intra_add_stub(): this network is on remote router");
paul718e3742002-12-13 20:15:29 +0000628 ospf_route_copy_nexthops_from_vertex (or, v);
629 }
630 else
631 {
632 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000633 zlog_debug ("ospf_intra_add_stub(): this network is on this router");
paul718e3742002-12-13 20:15:29 +0000634
paul6d1fab62003-06-22 08:28:18 +0000635 if ((oi = ospf_if_lookup_by_prefix (area->ospf, &p)))
paul718e3742002-12-13 20:15:29 +0000636 {
637 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000638 zlog_debug ("ospf_intra_add_stub(): the interface is %s",
paul718e3742002-12-13 20:15:29 +0000639 IF_NAME (oi));
640
641 path = ospf_path_new ();
642 path->nexthop.s_addr = 0;
643 path->oi = oi;
paul96735ee2003-08-10 02:51:22 +0000644 listnode_add (or->paths, path);
paul718e3742002-12-13 20:15:29 +0000645 }
646 else
647 {
648 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000649 zlog_debug ("ospf_intra_add_stub(): where's the interface ?");
paul718e3742002-12-13 20:15:29 +0000650 }
651 }
652
653 rn->info = or;
654
655 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000656 zlog_debug("ospf_intra_add_stub(): Stop");
paul718e3742002-12-13 20:15:29 +0000657}
658
hassoeb1ce602004-10-08 08:17:22 +0000659const char *ospf_path_type_str[] =
paul718e3742002-12-13 20:15:29 +0000660{
661 "unknown-type",
662 "intra-area",
663 "inter-area",
664 "type1-external",
665 "type2-external"
666};
667
668void
669ospf_route_table_dump (struct route_table *rt)
670{
671 struct route_node *rn;
672 struct ospf_route *or;
673 char buf1[BUFSIZ];
674 char buf2[BUFSIZ];
hasso52dc7ee2004-09-23 19:18:23 +0000675 struct listnode *pnode;
paul718e3742002-12-13 20:15:29 +0000676 struct ospf_path *path;
677
678#if 0
ajs2a42e282004-12-08 18:43:03 +0000679 zlog_debug ("Type Dest Area Path Type Cost Next Adv.");
680 zlog_debug (" Hop(s) Router(s)");
paul718e3742002-12-13 20:15:29 +0000681#endif /* 0 */
682
ajs2a42e282004-12-08 18:43:03 +0000683 zlog_debug ("========== OSPF routing table ==========");
paul718e3742002-12-13 20:15:29 +0000684 for (rn = route_top (rt); rn; rn = route_next (rn))
685 if ((or = rn->info) != NULL)
686 {
687 if (or->type == OSPF_DESTINATION_NETWORK)
688 {
ajs2a42e282004-12-08 18:43:03 +0000689 zlog_debug ("N %s/%d\t%s\t%s\t%d",
paul718e3742002-12-13 20:15:29 +0000690 inet_ntop (AF_INET, &rn->p.u.prefix4, buf1, BUFSIZ),
691 rn->p.prefixlen,
692 inet_ntop (AF_INET, &or->u.std.area_id, buf2,
693 BUFSIZ),
694 ospf_path_type_str[or->path_type],
695 or->cost);
paul1eb8ef22005-04-07 07:30:20 +0000696 for (ALL_LIST_ELEMENTS_RO (or->paths, pnode, path))
697 zlog_debug (" -> %s", inet_ntoa (path->nexthop));
paul718e3742002-12-13 20:15:29 +0000698 }
699 else
ajs2a42e282004-12-08 18:43:03 +0000700 zlog_debug ("R %s\t%s\t%s\t%d",
paul718e3742002-12-13 20:15:29 +0000701 inet_ntop (AF_INET, &rn->p.u.prefix4, buf1, BUFSIZ),
702 inet_ntop (AF_INET, &or->u.std.area_id, buf2,
703 BUFSIZ),
704 ospf_path_type_str[or->path_type],
705 or->cost);
706 }
ajs2a42e282004-12-08 18:43:03 +0000707 zlog_debug ("========================================");
paul718e3742002-12-13 20:15:29 +0000708}
709
paul718e3742002-12-13 20:15:29 +0000710/* This is 16.4.1 implementation.
711 o Intra-area paths using non-backbone areas are always the most preferred.
712 o The other paths, intra-area backbone paths and inter-area paths,
713 are of equal preference. */
paul4dadc292005-05-06 21:37:42 +0000714static int
paul6d1fab62003-06-22 08:28:18 +0000715ospf_asbr_route_cmp (struct ospf *ospf, struct ospf_route *r1,
716 struct ospf_route *r2)
paul718e3742002-12-13 20:15:29 +0000717{
718 u_char r1_type, r2_type;
719
720 r1_type = r1->path_type;
721 r2_type = r2->path_type;
722
723 /* If RFC1583Compat flag is on -- all paths are equal. */
paul6d1fab62003-06-22 08:28:18 +0000724 if (CHECK_FLAG (ospf->config, OSPF_RFC1583_COMPATIBLE))
paul718e3742002-12-13 20:15:29 +0000725 return 0;
726
727 /* r1/r2 itself is backbone, and it's Inter-area path. */
728 if (OSPF_IS_AREA_ID_BACKBONE (r1->u.std.area_id))
729 r1_type = OSPF_PATH_INTER_AREA;
730 if (OSPF_IS_AREA_ID_BACKBONE (r2->u.std.area_id))
731 r2_type = OSPF_PATH_INTER_AREA;
732
733 return (r1_type - r2_type);
734}
735
736/* Compare two routes.
737 ret < 0 -- r1 is better.
738 ret == 0 -- r1 and r2 are the same.
739 ret > 0 -- r2 is better. */
740int
paul6d1fab62003-06-22 08:28:18 +0000741ospf_route_cmp (struct ospf *ospf, struct ospf_route *r1,
742 struct ospf_route *r2)
paul718e3742002-12-13 20:15:29 +0000743{
744 int ret = 0;
745
746 /* Path types of r1 and r2 are not the same. */
747 if ((ret = (r1->path_type - r2->path_type)))
748 return ret;
749
750 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000751 zlog_debug ("Route[Compare]: Path types are the same.");
paul718e3742002-12-13 20:15:29 +0000752 /* Path types are the same, compare any cost. */
753 switch (r1->path_type)
754 {
755 case OSPF_PATH_INTRA_AREA:
756 case OSPF_PATH_INTER_AREA:
757 break;
758 case OSPF_PATH_TYPE1_EXTERNAL:
paul6d1fab62003-06-22 08:28:18 +0000759 if (!CHECK_FLAG (ospf->config, OSPF_RFC1583_COMPATIBLE))
paul718e3742002-12-13 20:15:29 +0000760 {
paul6d1fab62003-06-22 08:28:18 +0000761 ret = ospf_asbr_route_cmp (ospf, r1->u.ext.asbr, r2->u.ext.asbr);
paul718e3742002-12-13 20:15:29 +0000762 if (ret != 0)
763 return ret;
764 }
765 break;
766 case OSPF_PATH_TYPE2_EXTERNAL:
767 if ((ret = (r1->u.ext.type2_cost - r2->u.ext.type2_cost)))
768 return ret;
769
paul6d1fab62003-06-22 08:28:18 +0000770 if (!CHECK_FLAG (ospf->config, OSPF_RFC1583_COMPATIBLE))
paul718e3742002-12-13 20:15:29 +0000771 {
paul6d1fab62003-06-22 08:28:18 +0000772 ret = ospf_asbr_route_cmp (ospf, r1->u.ext.asbr, r2->u.ext.asbr);
paul718e3742002-12-13 20:15:29 +0000773 if (ret != 0)
774 return ret;
775 }
776 break;
777 }
778
779 /* Anyway, compare the costs. */
780 return (r1->cost - r2->cost);
781}
782
paul4dadc292005-05-06 21:37:42 +0000783static int
paul718e3742002-12-13 20:15:29 +0000784ospf_path_exist (struct list *plist, struct in_addr nexthop,
785 struct ospf_interface *oi)
786{
paul1eb8ef22005-04-07 07:30:20 +0000787 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000788 struct ospf_path *path;
789
paul1eb8ef22005-04-07 07:30:20 +0000790 for (ALL_LIST_ELEMENTS (plist, node, nnode, path))
791 if (IPV4_ADDR_SAME (&path->nexthop, &nexthop) && path->oi == oi)
792 return 1;
paul718e3742002-12-13 20:15:29 +0000793
paul718e3742002-12-13 20:15:29 +0000794 return 0;
795}
796
797void
798ospf_route_copy_nexthops_from_vertex (struct ospf_route *to,
799 struct vertex *v)
800{
paul1eb8ef22005-04-07 07:30:20 +0000801 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000802 struct ospf_path *path;
803 struct vertex_nexthop *nexthop;
pauleb3da6d2005-10-18 04:20:33 +0000804 struct vertex_parent *vp;
paul718e3742002-12-13 20:15:29 +0000805
paul96735ee2003-08-10 02:51:22 +0000806 assert (to->paths);
paul718e3742002-12-13 20:15:29 +0000807
pauleb3da6d2005-10-18 04:20:33 +0000808 for (ALL_LIST_ELEMENTS_RO (v->parents, node, vp))
paul718e3742002-12-13 20:15:29 +0000809 {
pauleb3da6d2005-10-18 04:20:33 +0000810 nexthop = vp->nexthop;
811
paul718e3742002-12-13 20:15:29 +0000812 if (nexthop->oi != NULL)
813 {
paul96735ee2003-08-10 02:51:22 +0000814 if (! ospf_path_exist (to->paths, nexthop->router, nexthop->oi))
paul718e3742002-12-13 20:15:29 +0000815 {
816 path = ospf_path_new ();
817 path->nexthop = nexthop->router;
818 path->oi = nexthop->oi;
paul96735ee2003-08-10 02:51:22 +0000819 listnode_add (to->paths, path);
paul718e3742002-12-13 20:15:29 +0000820 }
821 }
822 }
823}
824
825struct ospf_path *
hasso52dc7ee2004-09-23 19:18:23 +0000826ospf_path_lookup (struct list *plist, struct ospf_path *path)
paul718e3742002-12-13 20:15:29 +0000827{
hasso52dc7ee2004-09-23 19:18:23 +0000828 struct listnode *node;
paul1eb8ef22005-04-07 07:30:20 +0000829 struct ospf_path *op;
paul718e3742002-12-13 20:15:29 +0000830
paul1eb8ef22005-04-07 07:30:20 +0000831 for (ALL_LIST_ELEMENTS_RO (plist, node, op))
Joakim Tjernlund77a1c4e2009-02-01 11:12:11 +0100832 {
833 if (!IPV4_ADDR_SAME (&op->nexthop, &path->nexthop))
834 continue;
835 if (!IPV4_ADDR_SAME (&op->adv_router, &path->adv_router))
836 continue;
837 if (op->oi->ifp->ifindex != path->oi->ifp->ifindex)
838 continue;
839 return op;
840 }
paul718e3742002-12-13 20:15:29 +0000841 return NULL;
842}
843
844void
hasso52dc7ee2004-09-23 19:18:23 +0000845ospf_route_copy_nexthops (struct ospf_route *to, struct list *from)
paul718e3742002-12-13 20:15:29 +0000846{
paul1eb8ef22005-04-07 07:30:20 +0000847 struct listnode *node, *nnode;
848 struct ospf_path *path;
paul718e3742002-12-13 20:15:29 +0000849
paul96735ee2003-08-10 02:51:22 +0000850 assert (to->paths);
paul718e3742002-12-13 20:15:29 +0000851
paul1eb8ef22005-04-07 07:30:20 +0000852 for (ALL_LIST_ELEMENTS (from, node, nnode, path))
paul718e3742002-12-13 20:15:29 +0000853 /* The same routes are just discarded. */
paul1eb8ef22005-04-07 07:30:20 +0000854 if (!ospf_path_lookup (to->paths, path))
855 listnode_add (to->paths, ospf_path_dup (path));
paul718e3742002-12-13 20:15:29 +0000856}
857
858void
hasso52dc7ee2004-09-23 19:18:23 +0000859ospf_route_subst_nexthops (struct ospf_route *to, struct list *from)
paul718e3742002-12-13 20:15:29 +0000860{
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)
ajs2a42e282004-12-08 18:43:03 +0000891 zlog_debug ("ospf_route_add(): something's wrong !");
paul718e3742002-12-13 20:15:29 +0000892 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)
ajs2a42e282004-12-08 18:43:03 +0000906 zlog_debug ("Pruning unreachable networks");
paul718e3742002-12-13 20:15:29 +0000907
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)
ajs2a42e282004-12-08 18:43:03 +0000917 zlog_debug ("Pruning route to %s/%d",
paul718e3742002-12-13 20:15:29 +0000918 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;
paul1eb8ef22005-04-07 07:30:20 +0000933 struct listnode *node, *nnode;
hasso52dc7ee2004-09-23 19:18:23 +0000934 struct list *paths;
paul718e3742002-12-13 20:15:29 +0000935
936 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000937 zlog_debug ("Pruning unreachable routers");
paul718e3742002-12-13 20:15:29 +0000938
939 for (rn = route_top (rtrs); rn; rn = next)
940 {
941 next = route_next (rn);
942 if ((paths = rn->info) == NULL)
943 continue;
944
paul1eb8ef22005-04-07 07:30:20 +0000945 for (ALL_LIST_ELEMENTS (paths, node, nnode, or))
paul718e3742002-12-13 20:15:29 +0000946 {
paul96735ee2003-08-10 02:51:22 +0000947 if (listcount (or->paths) == 0)
paul718e3742002-12-13 20:15:29 +0000948 {
949 if (IS_DEBUG_OSPF_EVENT)
950 {
ajs2a42e282004-12-08 18:43:03 +0000951 zlog_debug ("Pruning route to rtr %s",
paul718e3742002-12-13 20:15:29 +0000952 inet_ntoa (rn->p.u.prefix4));
ajs2a42e282004-12-08 18:43:03 +0000953 zlog_debug (" via area %s",
paul718e3742002-12-13 20:15:29 +0000954 inet_ntoa (or->u.std.area_id));
955 }
956
957 listnode_delete (paths, or);
958 ospf_route_free (or);
959 }
960 }
961
962 if (listcount (paths) == 0)
963 {
964 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000965 zlog_debug ("Pruning router node %s", inet_ntoa (rn->p.u.prefix4));
paul718e3742002-12-13 20:15:29 +0000966
967 list_delete (paths);
968 rn->info = NULL;
969 route_unlock_node (rn);
970 }
971 }
972}
973
974int
975ospf_add_discard_route (struct route_table *rt, struct ospf_area *area,
976 struct prefix_ipv4 *p)
977{
978 struct route_node *rn;
979 struct ospf_route *or, *new_or;
980
981 rn = route_node_get (rt, (struct prefix *) p);
982
983 if (rn == NULL)
984 {
985 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000986 zlog_debug ("ospf_add_discard_route(): router installation error");
paul718e3742002-12-13 20:15:29 +0000987 return 0;
988 }
989
990 if (rn->info) /* If the route to the same destination is found */
991 {
992 route_unlock_node (rn);
993
994 or = rn->info;
995
996 if (or->path_type == OSPF_PATH_INTRA_AREA)
997 {
998 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000999 zlog_debug ("ospf_add_discard_route(): "
paul718e3742002-12-13 20:15:29 +00001000 "an intra-area route exists");
1001 return 0;
1002 }
1003
1004 if (or->type == OSPF_DESTINATION_DISCARD)
1005 {
1006 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001007 zlog_debug ("ospf_add_discard_route(): "
paul718e3742002-12-13 20:15:29 +00001008 "discard entry already installed");
1009 return 0;
1010 }
1011
1012 ospf_route_free (rn->info);
1013 }
1014
1015 new_or = ospf_route_new ();
1016 new_or->type = OSPF_DESTINATION_DISCARD;
1017 new_or->id.s_addr = 0;
1018 new_or->cost = 0;
1019 new_or->u.std.area_id = area->area_id;
paul718e3742002-12-13 20:15:29 +00001020 new_or->u.std.external_routing = area->external_routing;
paul718e3742002-12-13 20:15:29 +00001021 new_or->path_type = OSPF_PATH_INTER_AREA;
1022 rn->info = new_or;
1023
1024 ospf_zebra_add_discard (p);
1025
1026 return 1;
1027}
1028
1029void
1030ospf_delete_discard_route (struct prefix_ipv4 *p)
1031{
1032 ospf_zebra_delete_discard(p);
1033}
1034