blob: 3a1fa9992445fc09a23035f9332abbb5cee9efc2 [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/*
2 * OSPF routing table.
3 * Copyright (C) 1999, 2000 Toshiaki Takada
4 *
5 * This file is part of GNU Zebra.
6 *
7 * GNU Zebra is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
10 * later version.
11 *
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with GNU Zebra; see the file COPYING. If not, write to the Free
19 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20 * 02111-1307, USA.
21 */
22
23#include <zebra.h>
24
25#include "prefix.h"
26#include "table.h"
27#include "memory.h"
28#include "linklist.h"
29#include "log.h"
30#include "if.h"
31#include "command.h"
32#include "sockunion.h"
33
34#include "ospfd/ospfd.h"
35#include "ospfd/ospf_interface.h"
36#include "ospfd/ospf_asbr.h"
37#include "ospfd/ospf_lsa.h"
38#include "ospfd/ospf_route.h"
39#include "ospfd/ospf_spf.h"
40#include "ospfd/ospf_zebra.h"
41#include "ospfd/ospf_dump.h"
42
43struct ospf_route *
44ospf_route_new ()
45{
46 struct ospf_route *new;
47
48 new = XCALLOC (MTYPE_OSPF_ROUTE, sizeof (struct ospf_route));
49
Paul Jakma2518efd2006-08-27 06:49:29 +000050 new->ctime = quagga_time (NULL);
paul718e3742002-12-13 20:15:29 +000051 new->mtime = new->ctime;
paul96735ee2003-08-10 02:51:22 +000052 new->paths = list_new ();
53 new->paths->del = (void (*) (void *))ospf_path_free;
paul718e3742002-12-13 20:15:29 +000054
55 return new;
56}
57
58void
59ospf_route_free (struct ospf_route *or)
60{
paul96735ee2003-08-10 02:51:22 +000061 if (or->paths)
62 list_delete (or->paths);
paul718e3742002-12-13 20:15:29 +000063
64 XFREE (MTYPE_OSPF_ROUTE, or);
65}
66
67struct ospf_path *
68ospf_path_new ()
69{
70 struct ospf_path *new;
71
72 new = XCALLOC (MTYPE_OSPF_PATH, sizeof (struct ospf_path));
73
74 return new;
75}
76
paul4dadc292005-05-06 21:37:42 +000077static struct ospf_path *
paul718e3742002-12-13 20:15:29 +000078ospf_path_dup (struct ospf_path *path)
79{
80 struct ospf_path *new;
81
82 new = ospf_path_new ();
83 memcpy (new, path, sizeof (struct ospf_path));
84
85 return new;
86}
87
88void
89ospf_path_free (struct ospf_path *op)
90{
91 XFREE (MTYPE_OSPF_PATH, op);
92}
93
94void
95ospf_route_delete (struct route_table *rt)
96{
97 struct route_node *rn;
98 struct ospf_route *or;
99
100 for (rn = route_top (rt); rn; rn = route_next (rn))
101 if ((or = rn->info) != NULL)
102 {
103 if (or->type == OSPF_DESTINATION_NETWORK)
104 ospf_zebra_delete ((struct prefix_ipv4 *) &rn->p,
105 or);
106 else if (or->type == OSPF_DESTINATION_DISCARD)
107 ospf_zebra_delete_discard ((struct prefix_ipv4 *) &rn->p);
108 }
109}
110
111void
112ospf_route_table_free (struct route_table *rt)
113{
114 struct route_node *rn;
115 struct ospf_route *or;
116
117 for (rn = route_top (rt); rn; rn = route_next (rn))
118 if ((or = rn->info) != NULL)
119 {
120 ospf_route_free (or);
121
122 rn->info = NULL;
123 route_unlock_node (rn);
124 }
125
126 route_table_finish (rt);
127}
128
129/* If a prefix and a nexthop match any route in the routing table,
130 then return 1, otherwise return 0. */
131int
132ospf_route_match_same (struct route_table *rt, struct prefix_ipv4 *prefix,
133 struct ospf_route *newor)
134{
135 struct route_node *rn;
136 struct ospf_route *or;
137 struct ospf_path *op;
138 struct ospf_path *newop;
hasso52dc7ee2004-09-23 19:18:23 +0000139 struct listnode *n1;
140 struct listnode *n2;
paul718e3742002-12-13 20:15:29 +0000141
142 if (! rt || ! prefix)
143 return 0;
144
145 rn = route_node_lookup (rt, (struct prefix *) prefix);
146 if (! rn || ! rn->info)
147 return 0;
148
149 route_unlock_node (rn);
150
151 or = rn->info;
152 if (or->type == newor->type && or->cost == newor->cost)
153 {
154 if (or->type == OSPF_DESTINATION_NETWORK)
155 {
paul96735ee2003-08-10 02:51:22 +0000156 if (or->paths->count != newor->paths->count)
paul718e3742002-12-13 20:15:29 +0000157 return 0;
158
159 /* Check each path. */
paul96735ee2003-08-10 02:51:22 +0000160 for (n1 = listhead (or->paths), n2 = listhead (newor->paths);
paul1eb8ef22005-04-07 07:30:20 +0000161 n1 && n2; n1 = listnextnode (n1), n2 = listnextnode (n2))
paul718e3742002-12-13 20:15:29 +0000162 {
paul1eb8ef22005-04-07 07:30:20 +0000163 op = listgetdata (n1);
164 newop = listgetdata (n2);
paul718e3742002-12-13 20:15:29 +0000165
166 if (! IPV4_ADDR_SAME (&op->nexthop, &newop->nexthop))
167 return 0;
168 }
169 return 1;
170 }
171 else if (prefix_same (&rn->p, (struct prefix *) prefix))
172 return 1;
173 }
174 return 0;
175}
176
paul6d1fab62003-06-22 08:28:18 +0000177/* delete routes generated from AS-External routes if there is a inter/intra
178 * area route
179 */
paul4dadc292005-05-06 21:37:42 +0000180static void
paul6d1fab62003-06-22 08:28:18 +0000181ospf_route_delete_same_ext(struct route_table *external_routes,
182 struct route_table *routes)
183{
184 struct route_node *rn,
185 *ext_rn;
186
187 if ( (external_routes == NULL) || (routes == NULL) )
188 return;
189
190 /* Remove deleted routes */
191 for ( rn = route_top (routes); rn; rn = route_next (rn) )
192 {
193 if (rn && rn->info)
194 {
hassofa2b17e2004-03-04 17:45:00 +0000195 struct prefix_ipv4 *p = (struct prefix_ipv4 *)(&rn->p);
196 if ( (ext_rn = route_node_lookup (external_routes, (struct prefix *)p)) )
paul6d1fab62003-06-22 08:28:18 +0000197 {
paul6d1fab62003-06-22 08:28:18 +0000198 if (ext_rn->info)
199 {
Paul Jakma894f8b62006-05-12 22:50:40 +0000200 ospf_zebra_delete (p, ext_rn->info);
paul6d1fab62003-06-22 08:28:18 +0000201 ospf_route_free( ext_rn->info);
202 ext_rn->info = NULL;
203 }
204 route_unlock_node (ext_rn);
205 }
206 }
207 }
208}
209
paul718e3742002-12-13 20:15:29 +0000210/* rt: Old, cmprt: New */
paul4dadc292005-05-06 21:37:42 +0000211static void
paul718e3742002-12-13 20:15:29 +0000212ospf_route_delete_uniq (struct route_table *rt, struct route_table *cmprt)
213{
214 struct route_node *rn;
215 struct ospf_route *or;
216
217 for (rn = route_top (rt); rn; rn = route_next (rn))
218 if ((or = rn->info) != NULL)
219 if (or->path_type == OSPF_PATH_INTRA_AREA ||
220 or->path_type == OSPF_PATH_INTER_AREA)
221 {
222 if (or->type == OSPF_DESTINATION_NETWORK)
223 {
224 if (! ospf_route_match_same (cmprt,
225 (struct prefix_ipv4 *) &rn->p, or))
226 ospf_zebra_delete ((struct prefix_ipv4 *) &rn->p, or);
227 }
228 else if (or->type == OSPF_DESTINATION_DISCARD)
229 if (! ospf_route_match_same (cmprt,
230 (struct prefix_ipv4 *) &rn->p, or))
231 ospf_zebra_delete_discard ((struct prefix_ipv4 *) &rn->p);
232 }
233}
234
235/* Install routes to table. */
236void
paul6d1fab62003-06-22 08:28:18 +0000237ospf_route_install (struct ospf *ospf, struct route_table *rt)
paul718e3742002-12-13 20:15:29 +0000238{
239 struct route_node *rn;
240 struct ospf_route *or;
241
242 /* rt contains new routing table, new_table contains an old one.
243 updating pointers */
paul6d1fab62003-06-22 08:28:18 +0000244 if (ospf->old_table)
245 ospf_route_table_free (ospf->old_table);
246
247 ospf->old_table = ospf->new_table;
248 ospf->new_table = rt;
paul718e3742002-12-13 20:15:29 +0000249
250 /* Delete old routes. */
paul6d1fab62003-06-22 08:28:18 +0000251 if (ospf->old_table)
252 ospf_route_delete_uniq (ospf->old_table, rt);
253 if (ospf->old_external_route)
254 ospf_route_delete_same_ext (ospf->old_external_route, rt);
paul718e3742002-12-13 20:15:29 +0000255
256 /* Install new routes. */
257 for (rn = route_top (rt); rn; rn = route_next (rn))
258 if ((or = rn->info) != NULL)
259 {
260 if (or->type == OSPF_DESTINATION_NETWORK)
261 {
paul6d1fab62003-06-22 08:28:18 +0000262 if (! ospf_route_match_same (ospf->old_table,
paul718e3742002-12-13 20:15:29 +0000263 (struct prefix_ipv4 *)&rn->p, or))
264 ospf_zebra_add ((struct prefix_ipv4 *) &rn->p, or);
265 }
266 else if (or->type == OSPF_DESTINATION_DISCARD)
paul6d1fab62003-06-22 08:28:18 +0000267 if (! ospf_route_match_same (ospf->old_table,
paul718e3742002-12-13 20:15:29 +0000268 (struct prefix_ipv4 *) &rn->p, or))
269 ospf_zebra_add_discard ((struct prefix_ipv4 *) &rn->p);
270 }
271}
272
paul4dadc292005-05-06 21:37:42 +0000273static void
paul718e3742002-12-13 20:15:29 +0000274ospf_intra_route_add (struct route_table *rt, struct vertex *v,
275 struct ospf_area *area)
276{
277 struct route_node *rn;
278 struct ospf_route *or;
279 struct prefix_ipv4 p;
280 struct ospf_path *path;
pauleb3da6d2005-10-18 04:20:33 +0000281 struct vertex_parent *parent;
paul1eb8ef22005-04-07 07:30:20 +0000282 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000283
284 p.family = AF_INET;
285 p.prefix = v->id;
286 if (v->type == OSPF_VERTEX_ROUTER)
287 p.prefixlen = IPV4_MAX_BITLEN;
288 else
289 {
290 struct network_lsa *lsa = (struct network_lsa *) v->lsa;
291 p.prefixlen = ip_masklen (lsa->mask);
292 }
293 apply_mask_ipv4 (&p);
294
295 rn = route_node_get (rt, (struct prefix *) &p);
296 if (rn->info)
297 {
298 zlog_warn ("Same routing information exists for %s", inet_ntoa (v->id));
299 route_unlock_node (rn);
300 return;
301 }
302
303 or = ospf_route_new ();
304
305 if (v->type == OSPF_VERTEX_NETWORK)
306 {
307 or->type = OSPF_DESTINATION_NETWORK;
paul718e3742002-12-13 20:15:29 +0000308
pauleb3da6d2005-10-18 04:20:33 +0000309 for (ALL_LIST_ELEMENTS (v->parents, node, nnode, parent))
paul96735ee2003-08-10 02:51:22 +0000310 {
paul96735ee2003-08-10 02:51:22 +0000311 path = ospf_path_new ();
pauleb3da6d2005-10-18 04:20:33 +0000312 path->nexthop = parent->nexthop->router;
paul96735ee2003-08-10 02:51:22 +0000313 listnode_add (or->paths, path);
314 }
paul718e3742002-12-13 20:15:29 +0000315 }
316 else
317 or->type = OSPF_DESTINATION_ROUTER;
318
319 or->id = v->id;
320 or->u.std.area_id = area->area_id;
paul718e3742002-12-13 20:15:29 +0000321 or->u.std.external_routing= area->external_routing;
paul718e3742002-12-13 20:15:29 +0000322 or->path_type = OSPF_PATH_INTRA_AREA;
323 or->cost = v->distance;
324
325 rn->info = or;
326}
327
328/* RFC2328 16.1. (4). For "router". */
329void
330ospf_intra_add_router (struct route_table *rt, struct vertex *v,
331 struct ospf_area *area)
332{
333 struct route_node *rn;
334 struct ospf_route *or;
335 struct prefix_ipv4 p;
336 struct router_lsa *lsa;
337
338 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000339 zlog_debug ("ospf_intra_add_router: Start");
paul718e3742002-12-13 20:15:29 +0000340
341 lsa = (struct router_lsa *) v->lsa;
342
343 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000344 zlog_debug ("ospf_intra_add_router: LS ID: %s",
paul718e3742002-12-13 20:15:29 +0000345 inet_ntoa (lsa->header.id));
Paul Jakma9c27ef92006-05-04 07:32:57 +0000346
347 if (!OSPF_IS_AREA_BACKBONE(area))
348 ospf_vl_up_check (area, lsa->header.id, v);
paul718e3742002-12-13 20:15:29 +0000349
350 if (!CHECK_FLAG (lsa->flags, ROUTER_LSA_SHORTCUT))
351 area->shortcut_capability = 0;
352
353 /* If the newly added vertex is an area border router or AS boundary
354 router, a routing table entry is added whose destination type is
355 "router". */
356 if (! IS_ROUTER_LSA_BORDER (lsa) && ! IS_ROUTER_LSA_EXTERNAL (lsa))
357 {
358 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000359 zlog_debug ("ospf_intra_add_router: "
paul718e3742002-12-13 20:15:29 +0000360 "this router is neither ASBR nor ABR, skipping it");
361 return;
362 }
363
364 /* Update ABR and ASBR count in this area. */
365 if (IS_ROUTER_LSA_BORDER (lsa))
366 area->abr_count++;
367 if (IS_ROUTER_LSA_EXTERNAL (lsa))
368 area->asbr_count++;
369
370 /* The Options field found in the associated router-LSA is copied
371 into the routing table entry's Optional capabilities field. Call
372 the newly added vertex Router X. */
373 or = ospf_route_new ();
374
375 or->id = v->id;
376 or->u.std.area_id = area->area_id;
paul718e3742002-12-13 20:15:29 +0000377 or->u.std.external_routing = area->external_routing;
paul718e3742002-12-13 20:15:29 +0000378 or->path_type = OSPF_PATH_INTRA_AREA;
379 or->cost = v->distance;
380 or->type = OSPF_DESTINATION_ROUTER;
381 or->u.std.origin = (struct lsa_header *) lsa;
382 or->u.std.options = lsa->header.options;
383 or->u.std.flags = lsa->flags;
384
385 /* If Router X is the endpoint of one of the calculating router's
386 virtual links, and the virtual link uses Area A as Transit area:
387 the virtual link is declared up, the IP address of the virtual
388 interface is set to the IP address of the outgoing interface
389 calculated above for Router X, and the virtual neighbor's IP
390 address is set to Router X's interface address (contained in
391 Router X's router-LSA) that points back to the root of the
392 shortest- path tree; equivalently, this is the interface that
393 points back to Router X's parent vertex on the shortest-path tree
394 (similar to the calculation in Section 16.1.1). */
395
396 p.family = AF_INET;
397 p.prefix = v->id;
398 p.prefixlen = IPV4_MAX_BITLEN;
399
400 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000401 zlog_debug ("ospf_intra_add_router: talking about %s/%d",
paul718e3742002-12-13 20:15:29 +0000402 inet_ntoa (p.prefix), p.prefixlen);
403
404 rn = route_node_get (rt, (struct prefix *) &p);
405
406 /* Note that we keep all routes to ABRs and ASBRs, not only the best */
407 if (rn->info == NULL)
408 rn->info = list_new ();
409 else
410 route_unlock_node (rn);
411
412 ospf_route_copy_nexthops_from_vertex (or, v);
413
414 listnode_add (rn->info, or);
415
hasso9e1be242004-04-20 03:50:59 +0000416 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000417 zlog_debug ("ospf_intra_add_router: Stop");
paul718e3742002-12-13 20:15:29 +0000418}
419
420/* RFC2328 16.1. (4). For transit network. */
421void
422ospf_intra_add_transit (struct route_table *rt, struct vertex *v,
423 struct ospf_area *area)
424{
425 struct route_node *rn;
426 struct ospf_route *or;
427 struct prefix_ipv4 p;
428 struct network_lsa *lsa;
429
430 lsa = (struct network_lsa*) v->lsa;
431
432 /* If the newly added vertex is a transit network, the routing table
433 entry for the network is located. The entry's Destination ID is
434 the IP network number, which can be obtained by masking the
435 Vertex ID (Link State ID) with its associated subnet mask (found
436 in the body of the associated network-LSA). */
437 p.family = AF_INET;
438 p.prefix = v->id;
439 p.prefixlen = ip_masklen (lsa->mask);
440 apply_mask_ipv4 (&p);
441
442 rn = route_node_get (rt, (struct prefix *) &p);
443
444 /* If the routing table entry already exists (i.e., there is already
445 an intra-area route to the destination installed in the routing
446 table), multiple vertices have mapped to the same IP network.
447 For example, this can occur when a new Designated Router is being
448 established. In this case, the current routing table entry
449 should be overwritten if and only if the newly found path is just
450 as short and the current routing table entry's Link State Origin
451 has a smaller Link State ID than the newly added vertex' LSA. */
452 if (rn->info)
453 {
454 struct ospf_route *cur_or;
455
456 route_unlock_node (rn);
457 cur_or = rn->info;
458
459 if (v->distance > cur_or->cost ||
460 IPV4_ADDR_CMP (&cur_or->u.std.origin->id, &lsa->header.id) > 0)
461 return;
462
463 ospf_route_free (rn->info);
464 }
465
466 or = ospf_route_new ();
467
468 or->id = v->id;
469 or->u.std.area_id = area->area_id;
paul718e3742002-12-13 20:15:29 +0000470 or->u.std.external_routing = area->external_routing;
paul718e3742002-12-13 20:15:29 +0000471 or->path_type = OSPF_PATH_INTRA_AREA;
472 or->cost = v->distance;
473 or->type = OSPF_DESTINATION_NETWORK;
474 or->u.std.origin = (struct lsa_header *) lsa;
475
476 ospf_route_copy_nexthops_from_vertex (or, v);
477
478 rn->info = or;
479}
480
481/* RFC2328 16.1. second stage. */
482void
483ospf_intra_add_stub (struct route_table *rt, struct router_lsa_link *link,
484 struct vertex *v, struct ospf_area *area)
485{
486 u_int32_t cost;
487 struct route_node *rn;
488 struct ospf_route *or;
489 struct prefix_ipv4 p;
490 struct router_lsa *lsa;
491 struct ospf_interface *oi;
492 struct ospf_path *path;
493
494 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000495 zlog_debug ("ospf_intra_add_stub(): Start");
paul718e3742002-12-13 20:15:29 +0000496
497 lsa = (struct router_lsa *) v->lsa;
498
499 p.family = AF_INET;
500 p.prefix = link->link_id;
501 p.prefixlen = ip_masklen (link->link_data);
502 apply_mask_ipv4 (&p);
503
504 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000505 zlog_debug ("ospf_intra_add_stub(): processing route to %s/%d",
paul718e3742002-12-13 20:15:29 +0000506 inet_ntoa (p.prefix), p.prefixlen);
507
508 /* (1) Calculate the distance D of stub network from the root. D is
509 equal to the distance from the root to the router vertex
510 (calculated in stage 1), plus the stub network link's advertised
511 cost. */
512 cost = v->distance + ntohs (link->m[0].metric);
513
514 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000515 zlog_debug ("ospf_intra_add_stub(): calculated cost is %d + %d = %d",
paul718e3742002-12-13 20:15:29 +0000516 v->distance, ntohs(link->m[0].metric), cost);
517
518 rn = route_node_get (rt, (struct prefix *) &p);
519
520 /* Lookup current routing table. */
521 if (rn->info)
522 {
523 struct ospf_route *cur_or;
524
525 route_unlock_node (rn);
526
527 cur_or = rn->info;
528
529 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000530 zlog_debug ("ospf_intra_add_stub(): "
gdt630e4802004-08-31 17:28:41 +0000531 "another route to the same prefix found with cost %u",
532 cur_or->cost);
paul718e3742002-12-13 20:15:29 +0000533
534 /* Compare this distance to the current best cost to the stub
535 network. This is done by looking up the stub network's
536 current routing table entry. If the calculated distance D is
537 larger, go on to examine the next stub network link in the
538 LSA. */
539 if (cost > cur_or->cost)
540 {
541 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000542 zlog_debug ("ospf_intra_add_stub(): old route is better, exit");
paul718e3742002-12-13 20:15:29 +0000543 return;
544 }
545
546 /* (2) If this step is reached, the stub network's routing table
547 entry must be updated. Calculate the set of next hops that
548 would result from using the stub network link. This
549 calculation is shown in Section 16.1.1; input to this
550 calculation is the destination (the stub network) and the
551 parent vertex (the router vertex). If the distance D is the
552 same as the current routing table cost, simply add this set
553 of next hops to the routing table entry's list of next hops.
554 In this case, the routing table already has a Link State
555 Origin. If this Link State Origin is a router-LSA whose Link
556 State ID is smaller than V's Router ID, reset the Link State
557 Origin to V's router-LSA. */
558
559 if (cost == cur_or->cost)
560 {
561 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000562 zlog_debug ("ospf_intra_add_stub(): routes are equal, merge");
paul718e3742002-12-13 20:15:29 +0000563
564 ospf_route_copy_nexthops_from_vertex (cur_or, v);
565
566 if (IPV4_ADDR_CMP (&cur_or->u.std.origin->id, &lsa->header.id) < 0)
567 cur_or->u.std.origin = (struct lsa_header *) lsa;
568 return;
569 }
570
571 /* Otherwise D is smaller than the routing table cost.
572 Overwrite the current routing table entry by setting the
573 routing table entry's cost to D, and by setting the entry's
574 list of next hops to the newly calculated set. Set the
575 routing table entry's Link State Origin to V's router-LSA.
576 Then go on to examine the next stub network link. */
577
578 if (cost < cur_or->cost)
579 {
580 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000581 zlog_debug ("ospf_intra_add_stub(): new route is better, set it");
paul718e3742002-12-13 20:15:29 +0000582
583 cur_or->cost = cost;
584
paul048ba1d2003-08-15 16:04:21 +0000585 list_delete_all_node (cur_or->paths);
paul718e3742002-12-13 20:15:29 +0000586
587 ospf_route_copy_nexthops_from_vertex (cur_or, v);
588
589 cur_or->u.std.origin = (struct lsa_header *) lsa;
590 return;
591 }
592 }
593
594 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000595 zlog_debug ("ospf_intra_add_stub(): installing new route");
paul718e3742002-12-13 20:15:29 +0000596
597 or = ospf_route_new ();
598
599 or->id = v->id;
600 or->u.std.area_id = area->area_id;
paul718e3742002-12-13 20:15:29 +0000601 or->u.std.external_routing = area->external_routing;
paul718e3742002-12-13 20:15:29 +0000602 or->path_type = OSPF_PATH_INTRA_AREA;
603 or->cost = cost;
604 or->type = OSPF_DESTINATION_NETWORK;
605 or->u.std.origin = (struct lsa_header *) lsa;
paul718e3742002-12-13 20:15:29 +0000606
607 /* Nexthop is depend on connection type. */
608 if (v != area->spf)
609 {
610 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000611 zlog_debug ("ospf_intra_add_stub(): this network is on remote router");
paul718e3742002-12-13 20:15:29 +0000612 ospf_route_copy_nexthops_from_vertex (or, v);
613 }
614 else
615 {
616 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000617 zlog_debug ("ospf_intra_add_stub(): this network is on this router");
paul718e3742002-12-13 20:15:29 +0000618
paul6d1fab62003-06-22 08:28:18 +0000619 if ((oi = ospf_if_lookup_by_prefix (area->ospf, &p)))
paul718e3742002-12-13 20:15:29 +0000620 {
621 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000622 zlog_debug ("ospf_intra_add_stub(): the interface is %s",
paul718e3742002-12-13 20:15:29 +0000623 IF_NAME (oi));
624
625 path = ospf_path_new ();
626 path->nexthop.s_addr = 0;
627 path->oi = oi;
paul96735ee2003-08-10 02:51:22 +0000628 listnode_add (or->paths, path);
paul718e3742002-12-13 20:15:29 +0000629 }
630 else
631 {
632 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000633 zlog_debug ("ospf_intra_add_stub(): where's the interface ?");
paul718e3742002-12-13 20:15:29 +0000634 }
635 }
636
637 rn->info = or;
638
639 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000640 zlog_debug("ospf_intra_add_stub(): Stop");
paul718e3742002-12-13 20:15:29 +0000641}
642
hassoeb1ce602004-10-08 08:17:22 +0000643const char *ospf_path_type_str[] =
paul718e3742002-12-13 20:15:29 +0000644{
645 "unknown-type",
646 "intra-area",
647 "inter-area",
648 "type1-external",
649 "type2-external"
650};
651
652void
653ospf_route_table_dump (struct route_table *rt)
654{
655 struct route_node *rn;
656 struct ospf_route *or;
657 char buf1[BUFSIZ];
658 char buf2[BUFSIZ];
hasso52dc7ee2004-09-23 19:18:23 +0000659 struct listnode *pnode;
paul718e3742002-12-13 20:15:29 +0000660 struct ospf_path *path;
661
662#if 0
ajs2a42e282004-12-08 18:43:03 +0000663 zlog_debug ("Type Dest Area Path Type Cost Next Adv.");
664 zlog_debug (" Hop(s) Router(s)");
paul718e3742002-12-13 20:15:29 +0000665#endif /* 0 */
666
ajs2a42e282004-12-08 18:43:03 +0000667 zlog_debug ("========== OSPF routing table ==========");
paul718e3742002-12-13 20:15:29 +0000668 for (rn = route_top (rt); rn; rn = route_next (rn))
669 if ((or = rn->info) != NULL)
670 {
671 if (or->type == OSPF_DESTINATION_NETWORK)
672 {
ajs2a42e282004-12-08 18:43:03 +0000673 zlog_debug ("N %s/%d\t%s\t%s\t%d",
paul718e3742002-12-13 20:15:29 +0000674 inet_ntop (AF_INET, &rn->p.u.prefix4, buf1, BUFSIZ),
675 rn->p.prefixlen,
676 inet_ntop (AF_INET, &or->u.std.area_id, buf2,
677 BUFSIZ),
678 ospf_path_type_str[or->path_type],
679 or->cost);
paul1eb8ef22005-04-07 07:30:20 +0000680 for (ALL_LIST_ELEMENTS_RO (or->paths, pnode, path))
681 zlog_debug (" -> %s", inet_ntoa (path->nexthop));
paul718e3742002-12-13 20:15:29 +0000682 }
683 else
ajs2a42e282004-12-08 18:43:03 +0000684 zlog_debug ("R %s\t%s\t%s\t%d",
paul718e3742002-12-13 20:15:29 +0000685 inet_ntop (AF_INET, &rn->p.u.prefix4, buf1, BUFSIZ),
686 inet_ntop (AF_INET, &or->u.std.area_id, buf2,
687 BUFSIZ),
688 ospf_path_type_str[or->path_type],
689 or->cost);
690 }
ajs2a42e282004-12-08 18:43:03 +0000691 zlog_debug ("========================================");
paul718e3742002-12-13 20:15:29 +0000692}
693
paul718e3742002-12-13 20:15:29 +0000694/* This is 16.4.1 implementation.
695 o Intra-area paths using non-backbone areas are always the most preferred.
696 o The other paths, intra-area backbone paths and inter-area paths,
697 are of equal preference. */
paul4dadc292005-05-06 21:37:42 +0000698static int
paul6d1fab62003-06-22 08:28:18 +0000699ospf_asbr_route_cmp (struct ospf *ospf, struct ospf_route *r1,
700 struct ospf_route *r2)
paul718e3742002-12-13 20:15:29 +0000701{
702 u_char r1_type, r2_type;
703
704 r1_type = r1->path_type;
705 r2_type = r2->path_type;
706
707 /* If RFC1583Compat flag is on -- all paths are equal. */
paul6d1fab62003-06-22 08:28:18 +0000708 if (CHECK_FLAG (ospf->config, OSPF_RFC1583_COMPATIBLE))
paul718e3742002-12-13 20:15:29 +0000709 return 0;
710
711 /* r1/r2 itself is backbone, and it's Inter-area path. */
712 if (OSPF_IS_AREA_ID_BACKBONE (r1->u.std.area_id))
713 r1_type = OSPF_PATH_INTER_AREA;
714 if (OSPF_IS_AREA_ID_BACKBONE (r2->u.std.area_id))
715 r2_type = OSPF_PATH_INTER_AREA;
716
717 return (r1_type - r2_type);
718}
719
720/* Compare two routes.
721 ret < 0 -- r1 is better.
722 ret == 0 -- r1 and r2 are the same.
723 ret > 0 -- r2 is better. */
724int
paul6d1fab62003-06-22 08:28:18 +0000725ospf_route_cmp (struct ospf *ospf, struct ospf_route *r1,
726 struct ospf_route *r2)
paul718e3742002-12-13 20:15:29 +0000727{
728 int ret = 0;
729
730 /* Path types of r1 and r2 are not the same. */
731 if ((ret = (r1->path_type - r2->path_type)))
732 return ret;
733
734 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000735 zlog_debug ("Route[Compare]: Path types are the same.");
paul718e3742002-12-13 20:15:29 +0000736 /* Path types are the same, compare any cost. */
737 switch (r1->path_type)
738 {
739 case OSPF_PATH_INTRA_AREA:
740 case OSPF_PATH_INTER_AREA:
741 break;
742 case OSPF_PATH_TYPE1_EXTERNAL:
paul6d1fab62003-06-22 08:28:18 +0000743 if (!CHECK_FLAG (ospf->config, OSPF_RFC1583_COMPATIBLE))
paul718e3742002-12-13 20:15:29 +0000744 {
paul6d1fab62003-06-22 08:28:18 +0000745 ret = ospf_asbr_route_cmp (ospf, r1->u.ext.asbr, r2->u.ext.asbr);
paul718e3742002-12-13 20:15:29 +0000746 if (ret != 0)
747 return ret;
748 }
749 break;
750 case OSPF_PATH_TYPE2_EXTERNAL:
751 if ((ret = (r1->u.ext.type2_cost - r2->u.ext.type2_cost)))
752 return ret;
753
paul6d1fab62003-06-22 08:28:18 +0000754 if (!CHECK_FLAG (ospf->config, OSPF_RFC1583_COMPATIBLE))
paul718e3742002-12-13 20:15:29 +0000755 {
paul6d1fab62003-06-22 08:28:18 +0000756 ret = ospf_asbr_route_cmp (ospf, r1->u.ext.asbr, r2->u.ext.asbr);
paul718e3742002-12-13 20:15:29 +0000757 if (ret != 0)
758 return ret;
759 }
760 break;
761 }
762
763 /* Anyway, compare the costs. */
764 return (r1->cost - r2->cost);
765}
766
paul4dadc292005-05-06 21:37:42 +0000767static int
paul718e3742002-12-13 20:15:29 +0000768ospf_path_exist (struct list *plist, struct in_addr nexthop,
769 struct ospf_interface *oi)
770{
paul1eb8ef22005-04-07 07:30:20 +0000771 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000772 struct ospf_path *path;
773
paul1eb8ef22005-04-07 07:30:20 +0000774 for (ALL_LIST_ELEMENTS (plist, node, nnode, path))
775 if (IPV4_ADDR_SAME (&path->nexthop, &nexthop) && path->oi == oi)
776 return 1;
paul718e3742002-12-13 20:15:29 +0000777
paul718e3742002-12-13 20:15:29 +0000778 return 0;
779}
780
781void
782ospf_route_copy_nexthops_from_vertex (struct ospf_route *to,
783 struct vertex *v)
784{
paul1eb8ef22005-04-07 07:30:20 +0000785 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000786 struct ospf_path *path;
787 struct vertex_nexthop *nexthop;
pauleb3da6d2005-10-18 04:20:33 +0000788 struct vertex_parent *vp;
paul718e3742002-12-13 20:15:29 +0000789
paul96735ee2003-08-10 02:51:22 +0000790 assert (to->paths);
paul718e3742002-12-13 20:15:29 +0000791
pauleb3da6d2005-10-18 04:20:33 +0000792 for (ALL_LIST_ELEMENTS_RO (v->parents, node, vp))
paul718e3742002-12-13 20:15:29 +0000793 {
pauleb3da6d2005-10-18 04:20:33 +0000794 nexthop = vp->nexthop;
795
paul718e3742002-12-13 20:15:29 +0000796 if (nexthop->oi != NULL)
797 {
paul96735ee2003-08-10 02:51:22 +0000798 if (! ospf_path_exist (to->paths, nexthop->router, nexthop->oi))
paul718e3742002-12-13 20:15:29 +0000799 {
800 path = ospf_path_new ();
801 path->nexthop = nexthop->router;
802 path->oi = nexthop->oi;
paul96735ee2003-08-10 02:51:22 +0000803 listnode_add (to->paths, path);
paul718e3742002-12-13 20:15:29 +0000804 }
805 }
806 }
807}
808
809struct ospf_path *
hasso52dc7ee2004-09-23 19:18:23 +0000810ospf_path_lookup (struct list *plist, struct ospf_path *path)
paul718e3742002-12-13 20:15:29 +0000811{
hasso52dc7ee2004-09-23 19:18:23 +0000812 struct listnode *node;
paul1eb8ef22005-04-07 07:30:20 +0000813 struct ospf_path *op;
paul718e3742002-12-13 20:15:29 +0000814
paul1eb8ef22005-04-07 07:30:20 +0000815 for (ALL_LIST_ELEMENTS_RO (plist, node, op))
816 if (IPV4_ADDR_SAME (&op->nexthop, &path->nexthop) &&
817 IPV4_ADDR_SAME (&op->adv_router, &path->adv_router))
818 return op;
paul718e3742002-12-13 20:15:29 +0000819
820 return NULL;
821}
822
823void
hasso52dc7ee2004-09-23 19:18:23 +0000824ospf_route_copy_nexthops (struct ospf_route *to, struct list *from)
paul718e3742002-12-13 20:15:29 +0000825{
paul1eb8ef22005-04-07 07:30:20 +0000826 struct listnode *node, *nnode;
827 struct ospf_path *path;
paul718e3742002-12-13 20:15:29 +0000828
paul96735ee2003-08-10 02:51:22 +0000829 assert (to->paths);
paul718e3742002-12-13 20:15:29 +0000830
paul1eb8ef22005-04-07 07:30:20 +0000831 for (ALL_LIST_ELEMENTS (from, node, nnode, path))
paul718e3742002-12-13 20:15:29 +0000832 /* The same routes are just discarded. */
paul1eb8ef22005-04-07 07:30:20 +0000833 if (!ospf_path_lookup (to->paths, path))
834 listnode_add (to->paths, ospf_path_dup (path));
paul718e3742002-12-13 20:15:29 +0000835}
836
837void
hasso52dc7ee2004-09-23 19:18:23 +0000838ospf_route_subst_nexthops (struct ospf_route *to, struct list *from)
paul718e3742002-12-13 20:15:29 +0000839{
paul718e3742002-12-13 20:15:29 +0000840
paul96735ee2003-08-10 02:51:22 +0000841 list_delete_all_node (to->paths);
paul718e3742002-12-13 20:15:29 +0000842 ospf_route_copy_nexthops (to, from);
843}
844
845void
846ospf_route_subst (struct route_node *rn, struct ospf_route *new_or,
847 struct ospf_route *over)
848{
849 route_lock_node (rn);
850 ospf_route_free (rn->info);
851
paul96735ee2003-08-10 02:51:22 +0000852 ospf_route_copy_nexthops (new_or, over->paths);
paul718e3742002-12-13 20:15:29 +0000853 rn->info = new_or;
854 route_unlock_node (rn);
855}
856
857void
858ospf_route_add (struct route_table *rt, struct prefix_ipv4 *p,
859 struct ospf_route *new_or, struct ospf_route *over)
860{
861 struct route_node *rn;
862
863 rn = route_node_get (rt, (struct prefix *) p);
864
paul96735ee2003-08-10 02:51:22 +0000865 ospf_route_copy_nexthops (new_or, over->paths);
paul718e3742002-12-13 20:15:29 +0000866
867 if (rn->info)
868 {
869 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000870 zlog_debug ("ospf_route_add(): something's wrong !");
paul718e3742002-12-13 20:15:29 +0000871 route_unlock_node (rn);
872 return;
873 }
874
875 rn->info = new_or;
876}
877
878void
879ospf_prune_unreachable_networks (struct route_table *rt)
880{
881 struct route_node *rn, *next;
882 struct ospf_route *or;
883
884 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000885 zlog_debug ("Pruning unreachable networks");
paul718e3742002-12-13 20:15:29 +0000886
887 for (rn = route_top (rt); rn; rn = next)
888 {
889 next = route_next (rn);
890 if (rn->info != NULL)
891 {
892 or = rn->info;
paul96735ee2003-08-10 02:51:22 +0000893 if (listcount (or->paths) == 0)
paul718e3742002-12-13 20:15:29 +0000894 {
895 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000896 zlog_debug ("Pruning route to %s/%d",
paul718e3742002-12-13 20:15:29 +0000897 inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen);
898
899 ospf_route_free (or);
900 rn->info = NULL;
901 route_unlock_node (rn);
902 }
903 }
904 }
905}
906
907void
908ospf_prune_unreachable_routers (struct route_table *rtrs)
909{
910 struct route_node *rn, *next;
911 struct ospf_route *or;
paul1eb8ef22005-04-07 07:30:20 +0000912 struct listnode *node, *nnode;
hasso52dc7ee2004-09-23 19:18:23 +0000913 struct list *paths;
paul718e3742002-12-13 20:15:29 +0000914
915 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000916 zlog_debug ("Pruning unreachable routers");
paul718e3742002-12-13 20:15:29 +0000917
918 for (rn = route_top (rtrs); rn; rn = next)
919 {
920 next = route_next (rn);
921 if ((paths = rn->info) == NULL)
922 continue;
923
paul1eb8ef22005-04-07 07:30:20 +0000924 for (ALL_LIST_ELEMENTS (paths, node, nnode, or))
paul718e3742002-12-13 20:15:29 +0000925 {
paul96735ee2003-08-10 02:51:22 +0000926 if (listcount (or->paths) == 0)
paul718e3742002-12-13 20:15:29 +0000927 {
928 if (IS_DEBUG_OSPF_EVENT)
929 {
ajs2a42e282004-12-08 18:43:03 +0000930 zlog_debug ("Pruning route to rtr %s",
paul718e3742002-12-13 20:15:29 +0000931 inet_ntoa (rn->p.u.prefix4));
ajs2a42e282004-12-08 18:43:03 +0000932 zlog_debug (" via area %s",
paul718e3742002-12-13 20:15:29 +0000933 inet_ntoa (or->u.std.area_id));
934 }
935
936 listnode_delete (paths, or);
937 ospf_route_free (or);
938 }
939 }
940
941 if (listcount (paths) == 0)
942 {
943 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000944 zlog_debug ("Pruning router node %s", inet_ntoa (rn->p.u.prefix4));
paul718e3742002-12-13 20:15:29 +0000945
946 list_delete (paths);
947 rn->info = NULL;
948 route_unlock_node (rn);
949 }
950 }
951}
952
953int
954ospf_add_discard_route (struct route_table *rt, struct ospf_area *area,
955 struct prefix_ipv4 *p)
956{
957 struct route_node *rn;
958 struct ospf_route *or, *new_or;
959
960 rn = route_node_get (rt, (struct prefix *) p);
961
962 if (rn == NULL)
963 {
964 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000965 zlog_debug ("ospf_add_discard_route(): router installation error");
paul718e3742002-12-13 20:15:29 +0000966 return 0;
967 }
968
969 if (rn->info) /* If the route to the same destination is found */
970 {
971 route_unlock_node (rn);
972
973 or = rn->info;
974
975 if (or->path_type == OSPF_PATH_INTRA_AREA)
976 {
977 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000978 zlog_debug ("ospf_add_discard_route(): "
paul718e3742002-12-13 20:15:29 +0000979 "an intra-area route exists");
980 return 0;
981 }
982
983 if (or->type == OSPF_DESTINATION_DISCARD)
984 {
985 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000986 zlog_debug ("ospf_add_discard_route(): "
paul718e3742002-12-13 20:15:29 +0000987 "discard entry already installed");
988 return 0;
989 }
990
991 ospf_route_free (rn->info);
992 }
993
994 new_or = ospf_route_new ();
995 new_or->type = OSPF_DESTINATION_DISCARD;
996 new_or->id.s_addr = 0;
997 new_or->cost = 0;
998 new_or->u.std.area_id = area->area_id;
paul718e3742002-12-13 20:15:29 +0000999 new_or->u.std.external_routing = area->external_routing;
paul718e3742002-12-13 20:15:29 +00001000 new_or->path_type = OSPF_PATH_INTER_AREA;
1001 rn->info = new_or;
1002
1003 ospf_zebra_add_discard (p);
1004
1005 return 1;
1006}
1007
1008void
1009ospf_delete_discard_route (struct prefix_ipv4 *p)
1010{
1011 ospf_zebra_delete_discard(p);
1012}
1013