blob: d77c7420acf10416fd4f8a815e7fc1f0a7a9def1 [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
paul718e3742002-12-13 20:15:29 +0000723 /* r1/r2 itself is backbone, and it's Inter-area path. */
724 if (OSPF_IS_AREA_ID_BACKBONE (r1->u.std.area_id))
725 r1_type = OSPF_PATH_INTER_AREA;
726 if (OSPF_IS_AREA_ID_BACKBONE (r2->u.std.area_id))
727 r2_type = OSPF_PATH_INTER_AREA;
728
729 return (r1_type - r2_type);
730}
731
732/* Compare two routes.
733 ret < 0 -- r1 is better.
734 ret == 0 -- r1 and r2 are the same.
735 ret > 0 -- r2 is better. */
736int
paul6d1fab62003-06-22 08:28:18 +0000737ospf_route_cmp (struct ospf *ospf, struct ospf_route *r1,
738 struct ospf_route *r2)
paul718e3742002-12-13 20:15:29 +0000739{
740 int ret = 0;
741
742 /* Path types of r1 and r2 are not the same. */
743 if ((ret = (r1->path_type - r2->path_type)))
744 return ret;
745
746 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000747 zlog_debug ("Route[Compare]: Path types are the same.");
paul718e3742002-12-13 20:15:29 +0000748 /* Path types are the same, compare any cost. */
749 switch (r1->path_type)
750 {
751 case OSPF_PATH_INTRA_AREA:
752 case OSPF_PATH_INTER_AREA:
753 break;
754 case OSPF_PATH_TYPE1_EXTERNAL:
paul6d1fab62003-06-22 08:28:18 +0000755 if (!CHECK_FLAG (ospf->config, OSPF_RFC1583_COMPATIBLE))
paul718e3742002-12-13 20:15:29 +0000756 {
paul6d1fab62003-06-22 08:28:18 +0000757 ret = ospf_asbr_route_cmp (ospf, r1->u.ext.asbr, r2->u.ext.asbr);
paul718e3742002-12-13 20:15:29 +0000758 if (ret != 0)
759 return ret;
760 }
761 break;
762 case OSPF_PATH_TYPE2_EXTERNAL:
763 if ((ret = (r1->u.ext.type2_cost - r2->u.ext.type2_cost)))
764 return ret;
765
paul6d1fab62003-06-22 08:28:18 +0000766 if (!CHECK_FLAG (ospf->config, OSPF_RFC1583_COMPATIBLE))
paul718e3742002-12-13 20:15:29 +0000767 {
paul6d1fab62003-06-22 08:28:18 +0000768 ret = ospf_asbr_route_cmp (ospf, r1->u.ext.asbr, r2->u.ext.asbr);
paul718e3742002-12-13 20:15:29 +0000769 if (ret != 0)
770 return ret;
771 }
772 break;
773 }
774
775 /* Anyway, compare the costs. */
776 return (r1->cost - r2->cost);
777}
778
paul4dadc292005-05-06 21:37:42 +0000779static int
paul718e3742002-12-13 20:15:29 +0000780ospf_path_exist (struct list *plist, struct in_addr nexthop,
781 struct ospf_interface *oi)
782{
paul1eb8ef22005-04-07 07:30:20 +0000783 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000784 struct ospf_path *path;
785
paul1eb8ef22005-04-07 07:30:20 +0000786 for (ALL_LIST_ELEMENTS (plist, node, nnode, path))
Joakim Tjernlunda8ba8472009-07-27 12:42:34 +0200787 if (IPV4_ADDR_SAME (&path->nexthop, &nexthop) &&
788 path->ifindex == oi->ifp->ifindex)
paul1eb8ef22005-04-07 07:30:20 +0000789 return 1;
paul718e3742002-12-13 20:15:29 +0000790
paul718e3742002-12-13 20:15:29 +0000791 return 0;
792}
793
794void
795ospf_route_copy_nexthops_from_vertex (struct ospf_route *to,
796 struct vertex *v)
797{
paul1eb8ef22005-04-07 07:30:20 +0000798 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000799 struct ospf_path *path;
800 struct vertex_nexthop *nexthop;
pauleb3da6d2005-10-18 04:20:33 +0000801 struct vertex_parent *vp;
paul718e3742002-12-13 20:15:29 +0000802
paul96735ee2003-08-10 02:51:22 +0000803 assert (to->paths);
paul718e3742002-12-13 20:15:29 +0000804
pauleb3da6d2005-10-18 04:20:33 +0000805 for (ALL_LIST_ELEMENTS_RO (v->parents, node, vp))
paul718e3742002-12-13 20:15:29 +0000806 {
pauleb3da6d2005-10-18 04:20:33 +0000807 nexthop = vp->nexthop;
808
paul718e3742002-12-13 20:15:29 +0000809 if (nexthop->oi != NULL)
810 {
paul96735ee2003-08-10 02:51:22 +0000811 if (! ospf_path_exist (to->paths, nexthop->router, nexthop->oi))
paul718e3742002-12-13 20:15:29 +0000812 {
813 path = ospf_path_new ();
814 path->nexthop = nexthop->router;
Joakim Tjernlunda8ba8472009-07-27 12:42:34 +0200815 path->ifindex = nexthop->oi->ifp->ifindex;
paul96735ee2003-08-10 02:51:22 +0000816 listnode_add (to->paths, path);
paul718e3742002-12-13 20:15:29 +0000817 }
818 }
819 }
820}
821
822struct ospf_path *
hasso52dc7ee2004-09-23 19:18:23 +0000823ospf_path_lookup (struct list *plist, struct ospf_path *path)
paul718e3742002-12-13 20:15:29 +0000824{
hasso52dc7ee2004-09-23 19:18:23 +0000825 struct listnode *node;
paul1eb8ef22005-04-07 07:30:20 +0000826 struct ospf_path *op;
paul718e3742002-12-13 20:15:29 +0000827
paul1eb8ef22005-04-07 07:30:20 +0000828 for (ALL_LIST_ELEMENTS_RO (plist, node, op))
Joakim Tjernlund77a1c4e2009-02-01 11:12:11 +0100829 {
830 if (!IPV4_ADDR_SAME (&op->nexthop, &path->nexthop))
831 continue;
832 if (!IPV4_ADDR_SAME (&op->adv_router, &path->adv_router))
833 continue;
Joakim Tjernlunda8ba8472009-07-27 12:42:34 +0200834 if (op->ifindex != path->ifindex)
Joakim Tjernlund77a1c4e2009-02-01 11:12:11 +0100835 continue;
836 return op;
837 }
paul718e3742002-12-13 20:15:29 +0000838 return NULL;
839}
840
841void
hasso52dc7ee2004-09-23 19:18:23 +0000842ospf_route_copy_nexthops (struct ospf_route *to, struct list *from)
paul718e3742002-12-13 20:15:29 +0000843{
paul1eb8ef22005-04-07 07:30:20 +0000844 struct listnode *node, *nnode;
845 struct ospf_path *path;
paul718e3742002-12-13 20:15:29 +0000846
paul96735ee2003-08-10 02:51:22 +0000847 assert (to->paths);
paul718e3742002-12-13 20:15:29 +0000848
paul1eb8ef22005-04-07 07:30:20 +0000849 for (ALL_LIST_ELEMENTS (from, node, nnode, path))
paul718e3742002-12-13 20:15:29 +0000850 /* The same routes are just discarded. */
paul1eb8ef22005-04-07 07:30:20 +0000851 if (!ospf_path_lookup (to->paths, path))
852 listnode_add (to->paths, ospf_path_dup (path));
paul718e3742002-12-13 20:15:29 +0000853}
854
855void
hasso52dc7ee2004-09-23 19:18:23 +0000856ospf_route_subst_nexthops (struct ospf_route *to, struct list *from)
paul718e3742002-12-13 20:15:29 +0000857{
paul718e3742002-12-13 20:15:29 +0000858
paul96735ee2003-08-10 02:51:22 +0000859 list_delete_all_node (to->paths);
paul718e3742002-12-13 20:15:29 +0000860 ospf_route_copy_nexthops (to, from);
861}
862
863void
864ospf_route_subst (struct route_node *rn, struct ospf_route *new_or,
865 struct ospf_route *over)
866{
867 route_lock_node (rn);
868 ospf_route_free (rn->info);
869
paul96735ee2003-08-10 02:51:22 +0000870 ospf_route_copy_nexthops (new_or, over->paths);
paul718e3742002-12-13 20:15:29 +0000871 rn->info = new_or;
872 route_unlock_node (rn);
873}
874
875void
876ospf_route_add (struct route_table *rt, struct prefix_ipv4 *p,
877 struct ospf_route *new_or, struct ospf_route *over)
878{
879 struct route_node *rn;
880
881 rn = route_node_get (rt, (struct prefix *) p);
882
paul96735ee2003-08-10 02:51:22 +0000883 ospf_route_copy_nexthops (new_or, over->paths);
paul718e3742002-12-13 20:15:29 +0000884
885 if (rn->info)
886 {
887 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000888 zlog_debug ("ospf_route_add(): something's wrong !");
paul718e3742002-12-13 20:15:29 +0000889 route_unlock_node (rn);
890 return;
891 }
892
893 rn->info = new_or;
894}
895
896void
897ospf_prune_unreachable_networks (struct route_table *rt)
898{
899 struct route_node *rn, *next;
900 struct ospf_route *or;
901
902 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000903 zlog_debug ("Pruning unreachable networks");
paul718e3742002-12-13 20:15:29 +0000904
905 for (rn = route_top (rt); rn; rn = next)
906 {
907 next = route_next (rn);
908 if (rn->info != NULL)
909 {
910 or = rn->info;
paul96735ee2003-08-10 02:51:22 +0000911 if (listcount (or->paths) == 0)
paul718e3742002-12-13 20:15:29 +0000912 {
913 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000914 zlog_debug ("Pruning route to %s/%d",
paul718e3742002-12-13 20:15:29 +0000915 inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen);
916
917 ospf_route_free (or);
918 rn->info = NULL;
919 route_unlock_node (rn);
920 }
921 }
922 }
923}
924
925void
926ospf_prune_unreachable_routers (struct route_table *rtrs)
927{
928 struct route_node *rn, *next;
929 struct ospf_route *or;
paul1eb8ef22005-04-07 07:30:20 +0000930 struct listnode *node, *nnode;
hasso52dc7ee2004-09-23 19:18:23 +0000931 struct list *paths;
paul718e3742002-12-13 20:15:29 +0000932
933 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000934 zlog_debug ("Pruning unreachable routers");
paul718e3742002-12-13 20:15:29 +0000935
936 for (rn = route_top (rtrs); rn; rn = next)
937 {
938 next = route_next (rn);
939 if ((paths = rn->info) == NULL)
940 continue;
941
paul1eb8ef22005-04-07 07:30:20 +0000942 for (ALL_LIST_ELEMENTS (paths, node, nnode, or))
paul718e3742002-12-13 20:15:29 +0000943 {
paul96735ee2003-08-10 02:51:22 +0000944 if (listcount (or->paths) == 0)
paul718e3742002-12-13 20:15:29 +0000945 {
946 if (IS_DEBUG_OSPF_EVENT)
947 {
ajs2a42e282004-12-08 18:43:03 +0000948 zlog_debug ("Pruning route to rtr %s",
paul718e3742002-12-13 20:15:29 +0000949 inet_ntoa (rn->p.u.prefix4));
ajs2a42e282004-12-08 18:43:03 +0000950 zlog_debug (" via area %s",
paul718e3742002-12-13 20:15:29 +0000951 inet_ntoa (or->u.std.area_id));
952 }
953
954 listnode_delete (paths, or);
955 ospf_route_free (or);
956 }
957 }
958
959 if (listcount (paths) == 0)
960 {
961 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000962 zlog_debug ("Pruning router node %s", inet_ntoa (rn->p.u.prefix4));
paul718e3742002-12-13 20:15:29 +0000963
964 list_delete (paths);
965 rn->info = NULL;
966 route_unlock_node (rn);
967 }
968 }
969}
970
971int
972ospf_add_discard_route (struct route_table *rt, struct ospf_area *area,
973 struct prefix_ipv4 *p)
974{
975 struct route_node *rn;
976 struct ospf_route *or, *new_or;
977
978 rn = route_node_get (rt, (struct prefix *) p);
979
980 if (rn == NULL)
981 {
982 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000983 zlog_debug ("ospf_add_discard_route(): router installation error");
paul718e3742002-12-13 20:15:29 +0000984 return 0;
985 }
986
987 if (rn->info) /* If the route to the same destination is found */
988 {
989 route_unlock_node (rn);
990
991 or = rn->info;
992
993 if (or->path_type == OSPF_PATH_INTRA_AREA)
994 {
995 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000996 zlog_debug ("ospf_add_discard_route(): "
paul718e3742002-12-13 20:15:29 +0000997 "an intra-area route exists");
998 return 0;
999 }
1000
1001 if (or->type == OSPF_DESTINATION_DISCARD)
1002 {
1003 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001004 zlog_debug ("ospf_add_discard_route(): "
paul718e3742002-12-13 20:15:29 +00001005 "discard entry already installed");
1006 return 0;
1007 }
1008
1009 ospf_route_free (rn->info);
1010 }
1011
1012 new_or = ospf_route_new ();
1013 new_or->type = OSPF_DESTINATION_DISCARD;
1014 new_or->id.s_addr = 0;
1015 new_or->cost = 0;
1016 new_or->u.std.area_id = area->area_id;
paul718e3742002-12-13 20:15:29 +00001017 new_or->u.std.external_routing = area->external_routing;
paul718e3742002-12-13 20:15:29 +00001018 new_or->path_type = OSPF_PATH_INTER_AREA;
1019 rn->info = new_or;
1020
1021 ospf_zebra_add_discard (p);
1022
1023 return 1;
1024}
1025
1026void
1027ospf_delete_discard_route (struct prefix_ipv4 *p)
1028{
1029 ospf_zebra_delete_discard(p);
1030}
1031