blob: 267237b8f57ca366c93683122ff93d6c84cb34c5 [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 Tjernlunda8ba8472009-07-27 12:42:34 +0200168 if (op->ifindex != newop->ifindex)
Joakim Tjernlund77a1c4e2009-02-01 11:12:11 +0100169 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;
Joakim Tjernlunda8ba8472009-07-27 12:42:34 +0200643 path->ifindex = oi->ifp->ifindex;
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))
Joakim Tjernlunda8ba8472009-07-27 12:42:34 +0200791 if (IPV4_ADDR_SAME (&path->nexthop, &nexthop) &&
792 path->ifindex == oi->ifp->ifindex)
paul1eb8ef22005-04-07 07:30:20 +0000793 return 1;
paul718e3742002-12-13 20:15:29 +0000794
paul718e3742002-12-13 20:15:29 +0000795 return 0;
796}
797
798void
799ospf_route_copy_nexthops_from_vertex (struct ospf_route *to,
800 struct vertex *v)
801{
paul1eb8ef22005-04-07 07:30:20 +0000802 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000803 struct ospf_path *path;
804 struct vertex_nexthop *nexthop;
pauleb3da6d2005-10-18 04:20:33 +0000805 struct vertex_parent *vp;
paul718e3742002-12-13 20:15:29 +0000806
paul96735ee2003-08-10 02:51:22 +0000807 assert (to->paths);
paul718e3742002-12-13 20:15:29 +0000808
pauleb3da6d2005-10-18 04:20:33 +0000809 for (ALL_LIST_ELEMENTS_RO (v->parents, node, vp))
paul718e3742002-12-13 20:15:29 +0000810 {
pauleb3da6d2005-10-18 04:20:33 +0000811 nexthop = vp->nexthop;
812
paul718e3742002-12-13 20:15:29 +0000813 if (nexthop->oi != NULL)
814 {
paul96735ee2003-08-10 02:51:22 +0000815 if (! ospf_path_exist (to->paths, nexthop->router, nexthop->oi))
paul718e3742002-12-13 20:15:29 +0000816 {
817 path = ospf_path_new ();
818 path->nexthop = nexthop->router;
Joakim Tjernlunda8ba8472009-07-27 12:42:34 +0200819 path->ifindex = nexthop->oi->ifp->ifindex;
paul96735ee2003-08-10 02:51:22 +0000820 listnode_add (to->paths, path);
paul718e3742002-12-13 20:15:29 +0000821 }
822 }
823 }
824}
825
826struct ospf_path *
hasso52dc7ee2004-09-23 19:18:23 +0000827ospf_path_lookup (struct list *plist, struct ospf_path *path)
paul718e3742002-12-13 20:15:29 +0000828{
hasso52dc7ee2004-09-23 19:18:23 +0000829 struct listnode *node;
paul1eb8ef22005-04-07 07:30:20 +0000830 struct ospf_path *op;
paul718e3742002-12-13 20:15:29 +0000831
paul1eb8ef22005-04-07 07:30:20 +0000832 for (ALL_LIST_ELEMENTS_RO (plist, node, op))
Joakim Tjernlund77a1c4e2009-02-01 11:12:11 +0100833 {
834 if (!IPV4_ADDR_SAME (&op->nexthop, &path->nexthop))
835 continue;
836 if (!IPV4_ADDR_SAME (&op->adv_router, &path->adv_router))
837 continue;
Joakim Tjernlunda8ba8472009-07-27 12:42:34 +0200838 if (op->ifindex != path->ifindex)
Joakim Tjernlund77a1c4e2009-02-01 11:12:11 +0100839 continue;
840 return op;
841 }
paul718e3742002-12-13 20:15:29 +0000842 return NULL;
843}
844
845void
hasso52dc7ee2004-09-23 19:18:23 +0000846ospf_route_copy_nexthops (struct ospf_route *to, struct list *from)
paul718e3742002-12-13 20:15:29 +0000847{
paul1eb8ef22005-04-07 07:30:20 +0000848 struct listnode *node, *nnode;
849 struct ospf_path *path;
paul718e3742002-12-13 20:15:29 +0000850
paul96735ee2003-08-10 02:51:22 +0000851 assert (to->paths);
paul718e3742002-12-13 20:15:29 +0000852
paul1eb8ef22005-04-07 07:30:20 +0000853 for (ALL_LIST_ELEMENTS (from, node, nnode, path))
paul718e3742002-12-13 20:15:29 +0000854 /* The same routes are just discarded. */
paul1eb8ef22005-04-07 07:30:20 +0000855 if (!ospf_path_lookup (to->paths, path))
856 listnode_add (to->paths, ospf_path_dup (path));
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)
ajs2a42e282004-12-08 18:43:03 +0000892 zlog_debug ("ospf_route_add(): something's wrong !");
paul718e3742002-12-13 20:15:29 +0000893 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)
ajs2a42e282004-12-08 18:43:03 +0000907 zlog_debug ("Pruning unreachable networks");
paul718e3742002-12-13 20:15:29 +0000908
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)
ajs2a42e282004-12-08 18:43:03 +0000918 zlog_debug ("Pruning route to %s/%d",
paul718e3742002-12-13 20:15:29 +0000919 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;
paul1eb8ef22005-04-07 07:30:20 +0000934 struct listnode *node, *nnode;
hasso52dc7ee2004-09-23 19:18:23 +0000935 struct list *paths;
paul718e3742002-12-13 20:15:29 +0000936
937 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000938 zlog_debug ("Pruning unreachable routers");
paul718e3742002-12-13 20:15:29 +0000939
940 for (rn = route_top (rtrs); rn; rn = next)
941 {
942 next = route_next (rn);
943 if ((paths = rn->info) == NULL)
944 continue;
945
paul1eb8ef22005-04-07 07:30:20 +0000946 for (ALL_LIST_ELEMENTS (paths, node, nnode, or))
paul718e3742002-12-13 20:15:29 +0000947 {
paul96735ee2003-08-10 02:51:22 +0000948 if (listcount (or->paths) == 0)
paul718e3742002-12-13 20:15:29 +0000949 {
950 if (IS_DEBUG_OSPF_EVENT)
951 {
ajs2a42e282004-12-08 18:43:03 +0000952 zlog_debug ("Pruning route to rtr %s",
paul718e3742002-12-13 20:15:29 +0000953 inet_ntoa (rn->p.u.prefix4));
ajs2a42e282004-12-08 18:43:03 +0000954 zlog_debug (" via area %s",
paul718e3742002-12-13 20:15:29 +0000955 inet_ntoa (or->u.std.area_id));
956 }
957
958 listnode_delete (paths, or);
959 ospf_route_free (or);
960 }
961 }
962
963 if (listcount (paths) == 0)
964 {
965 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000966 zlog_debug ("Pruning router node %s", inet_ntoa (rn->p.u.prefix4));
paul718e3742002-12-13 20:15:29 +0000967
968 list_delete (paths);
969 rn->info = NULL;
970 route_unlock_node (rn);
971 }
972 }
973}
974
975int
976ospf_add_discard_route (struct route_table *rt, struct ospf_area *area,
977 struct prefix_ipv4 *p)
978{
979 struct route_node *rn;
980 struct ospf_route *or, *new_or;
981
982 rn = route_node_get (rt, (struct prefix *) p);
983
984 if (rn == NULL)
985 {
986 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000987 zlog_debug ("ospf_add_discard_route(): router installation error");
paul718e3742002-12-13 20:15:29 +0000988 return 0;
989 }
990
991 if (rn->info) /* If the route to the same destination is found */
992 {
993 route_unlock_node (rn);
994
995 or = rn->info;
996
997 if (or->path_type == OSPF_PATH_INTRA_AREA)
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 "an intra-area route exists");
1002 return 0;
1003 }
1004
1005 if (or->type == OSPF_DESTINATION_DISCARD)
1006 {
1007 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001008 zlog_debug ("ospf_add_discard_route(): "
paul718e3742002-12-13 20:15:29 +00001009 "discard entry already installed");
1010 return 0;
1011 }
1012
1013 ospf_route_free (rn->info);
1014 }
1015
1016 new_or = ospf_route_new ();
1017 new_or->type = OSPF_DESTINATION_DISCARD;
1018 new_or->id.s_addr = 0;
1019 new_or->cost = 0;
1020 new_or->u.std.area_id = area->area_id;
paul718e3742002-12-13 20:15:29 +00001021 new_or->u.std.external_routing = area->external_routing;
paul718e3742002-12-13 20:15:29 +00001022 new_or->path_type = OSPF_PATH_INTER_AREA;
1023 rn->info = new_or;
1024
1025 ospf_zebra_add_discard (p);
1026
1027 return 1;
1028}
1029
1030void
1031ospf_delete_discard_route (struct prefix_ipv4 *p)
1032{
1033 ospf_zebra_delete_discard(p);
1034}
1035