blob: 5eedbd82e5cfb7605a18943fe2c99be366a637d2 [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
50 new->ctime = time (NULL);
51 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 {
198 ospf_zebra_delete (p, ext_rn->info);
199 if (ext_rn->info)
200 {
201 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));
346
347 ospf_vl_up_check (area, lsa->header.id, v);
348
349 if (!CHECK_FLAG (lsa->flags, ROUTER_LSA_SHORTCUT))
350 area->shortcut_capability = 0;
351
352 /* If the newly added vertex is an area border router or AS boundary
353 router, a routing table entry is added whose destination type is
354 "router". */
355 if (! IS_ROUTER_LSA_BORDER (lsa) && ! IS_ROUTER_LSA_EXTERNAL (lsa))
356 {
357 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000358 zlog_debug ("ospf_intra_add_router: "
paul718e3742002-12-13 20:15:29 +0000359 "this router is neither ASBR nor ABR, skipping it");
360 return;
361 }
362
363 /* Update ABR and ASBR count in this area. */
364 if (IS_ROUTER_LSA_BORDER (lsa))
365 area->abr_count++;
366 if (IS_ROUTER_LSA_EXTERNAL (lsa))
367 area->asbr_count++;
368
369 /* The Options field found in the associated router-LSA is copied
370 into the routing table entry's Optional capabilities field. Call
371 the newly added vertex Router X. */
372 or = ospf_route_new ();
373
374 or->id = v->id;
375 or->u.std.area_id = area->area_id;
paul718e3742002-12-13 20:15:29 +0000376 or->u.std.external_routing = area->external_routing;
paul718e3742002-12-13 20:15:29 +0000377 or->path_type = OSPF_PATH_INTRA_AREA;
378 or->cost = v->distance;
379 or->type = OSPF_DESTINATION_ROUTER;
380 or->u.std.origin = (struct lsa_header *) lsa;
381 or->u.std.options = lsa->header.options;
382 or->u.std.flags = lsa->flags;
383
384 /* If Router X is the endpoint of one of the calculating router's
385 virtual links, and the virtual link uses Area A as Transit area:
386 the virtual link is declared up, the IP address of the virtual
387 interface is set to the IP address of the outgoing interface
388 calculated above for Router X, and the virtual neighbor's IP
389 address is set to Router X's interface address (contained in
390 Router X's router-LSA) that points back to the root of the
391 shortest- path tree; equivalently, this is the interface that
392 points back to Router X's parent vertex on the shortest-path tree
393 (similar to the calculation in Section 16.1.1). */
394
395 p.family = AF_INET;
396 p.prefix = v->id;
397 p.prefixlen = IPV4_MAX_BITLEN;
398
399 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000400 zlog_debug ("ospf_intra_add_router: talking about %s/%d",
paul718e3742002-12-13 20:15:29 +0000401 inet_ntoa (p.prefix), p.prefixlen);
402
403 rn = route_node_get (rt, (struct prefix *) &p);
404
405 /* Note that we keep all routes to ABRs and ASBRs, not only the best */
406 if (rn->info == NULL)
407 rn->info = list_new ();
408 else
409 route_unlock_node (rn);
410
411 ospf_route_copy_nexthops_from_vertex (or, v);
412
413 listnode_add (rn->info, or);
414
hasso9e1be242004-04-20 03:50:59 +0000415 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000416 zlog_debug ("ospf_intra_add_router: Stop");
paul718e3742002-12-13 20:15:29 +0000417}
418
419/* RFC2328 16.1. (4). For transit network. */
420void
421ospf_intra_add_transit (struct route_table *rt, struct vertex *v,
422 struct ospf_area *area)
423{
424 struct route_node *rn;
425 struct ospf_route *or;
426 struct prefix_ipv4 p;
427 struct network_lsa *lsa;
428
429 lsa = (struct network_lsa*) v->lsa;
430
431 /* If the newly added vertex is a transit network, the routing table
432 entry for the network is located. The entry's Destination ID is
433 the IP network number, which can be obtained by masking the
434 Vertex ID (Link State ID) with its associated subnet mask (found
435 in the body of the associated network-LSA). */
436 p.family = AF_INET;
437 p.prefix = v->id;
438 p.prefixlen = ip_masklen (lsa->mask);
439 apply_mask_ipv4 (&p);
440
441 rn = route_node_get (rt, (struct prefix *) &p);
442
443 /* If the routing table entry already exists (i.e., there is already
444 an intra-area route to the destination installed in the routing
445 table), multiple vertices have mapped to the same IP network.
446 For example, this can occur when a new Designated Router is being
447 established. In this case, the current routing table entry
448 should be overwritten if and only if the newly found path is just
449 as short and the current routing table entry's Link State Origin
450 has a smaller Link State ID than the newly added vertex' LSA. */
451 if (rn->info)
452 {
453 struct ospf_route *cur_or;
454
455 route_unlock_node (rn);
456 cur_or = rn->info;
457
458 if (v->distance > cur_or->cost ||
459 IPV4_ADDR_CMP (&cur_or->u.std.origin->id, &lsa->header.id) > 0)
460 return;
461
462 ospf_route_free (rn->info);
463 }
464
465 or = ospf_route_new ();
466
467 or->id = v->id;
468 or->u.std.area_id = area->area_id;
paul718e3742002-12-13 20:15:29 +0000469 or->u.std.external_routing = area->external_routing;
paul718e3742002-12-13 20:15:29 +0000470 or->path_type = OSPF_PATH_INTRA_AREA;
471 or->cost = v->distance;
472 or->type = OSPF_DESTINATION_NETWORK;
473 or->u.std.origin = (struct lsa_header *) lsa;
474
475 ospf_route_copy_nexthops_from_vertex (or, v);
476
477 rn->info = or;
478}
479
480/* RFC2328 16.1. second stage. */
481void
482ospf_intra_add_stub (struct route_table *rt, struct router_lsa_link *link,
483 struct vertex *v, struct ospf_area *area)
484{
485 u_int32_t cost;
486 struct route_node *rn;
487 struct ospf_route *or;
488 struct prefix_ipv4 p;
489 struct router_lsa *lsa;
490 struct ospf_interface *oi;
491 struct ospf_path *path;
492
493 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000494 zlog_debug ("ospf_intra_add_stub(): Start");
paul718e3742002-12-13 20:15:29 +0000495
496 lsa = (struct router_lsa *) v->lsa;
497
498 p.family = AF_INET;
499 p.prefix = link->link_id;
500 p.prefixlen = ip_masklen (link->link_data);
501 apply_mask_ipv4 (&p);
502
503 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000504 zlog_debug ("ospf_intra_add_stub(): processing route to %s/%d",
paul718e3742002-12-13 20:15:29 +0000505 inet_ntoa (p.prefix), p.prefixlen);
506
507 /* (1) Calculate the distance D of stub network from the root. D is
508 equal to the distance from the root to the router vertex
509 (calculated in stage 1), plus the stub network link's advertised
510 cost. */
511 cost = v->distance + ntohs (link->m[0].metric);
512
513 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000514 zlog_debug ("ospf_intra_add_stub(): calculated cost is %d + %d = %d",
paul718e3742002-12-13 20:15:29 +0000515 v->distance, ntohs(link->m[0].metric), cost);
516
517 rn = route_node_get (rt, (struct prefix *) &p);
518
519 /* Lookup current routing table. */
520 if (rn->info)
521 {
522 struct ospf_route *cur_or;
523
524 route_unlock_node (rn);
525
526 cur_or = rn->info;
527
528 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000529 zlog_debug ("ospf_intra_add_stub(): "
gdt630e4802004-08-31 17:28:41 +0000530 "another route to the same prefix found with cost %u",
531 cur_or->cost);
paul718e3742002-12-13 20:15:29 +0000532
533 /* Compare this distance to the current best cost to the stub
534 network. This is done by looking up the stub network's
535 current routing table entry. If the calculated distance D is
536 larger, go on to examine the next stub network link in the
537 LSA. */
538 if (cost > cur_or->cost)
539 {
540 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000541 zlog_debug ("ospf_intra_add_stub(): old route is better, exit");
paul718e3742002-12-13 20:15:29 +0000542 return;
543 }
544
545 /* (2) If this step is reached, the stub network's routing table
546 entry must be updated. Calculate the set of next hops that
547 would result from using the stub network link. This
548 calculation is shown in Section 16.1.1; input to this
549 calculation is the destination (the stub network) and the
550 parent vertex (the router vertex). If the distance D is the
551 same as the current routing table cost, simply add this set
552 of next hops to the routing table entry's list of next hops.
553 In this case, the routing table already has a Link State
554 Origin. If this Link State Origin is a router-LSA whose Link
555 State ID is smaller than V's Router ID, reset the Link State
556 Origin to V's router-LSA. */
557
558 if (cost == cur_or->cost)
559 {
560 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000561 zlog_debug ("ospf_intra_add_stub(): routes are equal, merge");
paul718e3742002-12-13 20:15:29 +0000562
563 ospf_route_copy_nexthops_from_vertex (cur_or, v);
564
565 if (IPV4_ADDR_CMP (&cur_or->u.std.origin->id, &lsa->header.id) < 0)
566 cur_or->u.std.origin = (struct lsa_header *) lsa;
567 return;
568 }
569
570 /* Otherwise D is smaller than the routing table cost.
571 Overwrite the current routing table entry by setting the
572 routing table entry's cost to D, and by setting the entry's
573 list of next hops to the newly calculated set. Set the
574 routing table entry's Link State Origin to V's router-LSA.
575 Then go on to examine the next stub network link. */
576
577 if (cost < cur_or->cost)
578 {
579 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000580 zlog_debug ("ospf_intra_add_stub(): new route is better, set it");
paul718e3742002-12-13 20:15:29 +0000581
582 cur_or->cost = cost;
583
paul048ba1d2003-08-15 16:04:21 +0000584 list_delete_all_node (cur_or->paths);
paul718e3742002-12-13 20:15:29 +0000585
586 ospf_route_copy_nexthops_from_vertex (cur_or, v);
587
588 cur_or->u.std.origin = (struct lsa_header *) lsa;
589 return;
590 }
591 }
592
593 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000594 zlog_debug ("ospf_intra_add_stub(): installing new route");
paul718e3742002-12-13 20:15:29 +0000595
596 or = ospf_route_new ();
597
598 or->id = v->id;
599 or->u.std.area_id = area->area_id;
paul718e3742002-12-13 20:15:29 +0000600 or->u.std.external_routing = area->external_routing;
paul718e3742002-12-13 20:15:29 +0000601 or->path_type = OSPF_PATH_INTRA_AREA;
602 or->cost = cost;
603 or->type = OSPF_DESTINATION_NETWORK;
604 or->u.std.origin = (struct lsa_header *) lsa;
paul718e3742002-12-13 20:15:29 +0000605
606 /* Nexthop is depend on connection type. */
607 if (v != area->spf)
608 {
609 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000610 zlog_debug ("ospf_intra_add_stub(): this network is on remote router");
paul718e3742002-12-13 20:15:29 +0000611 ospf_route_copy_nexthops_from_vertex (or, v);
612 }
613 else
614 {
615 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000616 zlog_debug ("ospf_intra_add_stub(): this network is on this router");
paul718e3742002-12-13 20:15:29 +0000617
paul6d1fab62003-06-22 08:28:18 +0000618 if ((oi = ospf_if_lookup_by_prefix (area->ospf, &p)))
paul718e3742002-12-13 20:15:29 +0000619 {
620 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000621 zlog_debug ("ospf_intra_add_stub(): the interface is %s",
paul718e3742002-12-13 20:15:29 +0000622 IF_NAME (oi));
623
624 path = ospf_path_new ();
625 path->nexthop.s_addr = 0;
626 path->oi = oi;
paul96735ee2003-08-10 02:51:22 +0000627 listnode_add (or->paths, path);
paul718e3742002-12-13 20:15:29 +0000628 }
629 else
630 {
631 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000632 zlog_debug ("ospf_intra_add_stub(): where's the interface ?");
paul718e3742002-12-13 20:15:29 +0000633 }
634 }
635
636 rn->info = or;
637
638 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000639 zlog_debug("ospf_intra_add_stub(): Stop");
paul718e3742002-12-13 20:15:29 +0000640}
641
hassoeb1ce602004-10-08 08:17:22 +0000642const char *ospf_path_type_str[] =
paul718e3742002-12-13 20:15:29 +0000643{
644 "unknown-type",
645 "intra-area",
646 "inter-area",
647 "type1-external",
648 "type2-external"
649};
650
651void
652ospf_route_table_dump (struct route_table *rt)
653{
654 struct route_node *rn;
655 struct ospf_route *or;
656 char buf1[BUFSIZ];
657 char buf2[BUFSIZ];
hasso52dc7ee2004-09-23 19:18:23 +0000658 struct listnode *pnode;
paul718e3742002-12-13 20:15:29 +0000659 struct ospf_path *path;
660
661#if 0
ajs2a42e282004-12-08 18:43:03 +0000662 zlog_debug ("Type Dest Area Path Type Cost Next Adv.");
663 zlog_debug (" Hop(s) Router(s)");
paul718e3742002-12-13 20:15:29 +0000664#endif /* 0 */
665
ajs2a42e282004-12-08 18:43:03 +0000666 zlog_debug ("========== OSPF routing table ==========");
paul718e3742002-12-13 20:15:29 +0000667 for (rn = route_top (rt); rn; rn = route_next (rn))
668 if ((or = rn->info) != NULL)
669 {
670 if (or->type == OSPF_DESTINATION_NETWORK)
671 {
ajs2a42e282004-12-08 18:43:03 +0000672 zlog_debug ("N %s/%d\t%s\t%s\t%d",
paul718e3742002-12-13 20:15:29 +0000673 inet_ntop (AF_INET, &rn->p.u.prefix4, buf1, BUFSIZ),
674 rn->p.prefixlen,
675 inet_ntop (AF_INET, &or->u.std.area_id, buf2,
676 BUFSIZ),
677 ospf_path_type_str[or->path_type],
678 or->cost);
paul1eb8ef22005-04-07 07:30:20 +0000679 for (ALL_LIST_ELEMENTS_RO (or->paths, pnode, path))
680 zlog_debug (" -> %s", inet_ntoa (path->nexthop));
paul718e3742002-12-13 20:15:29 +0000681 }
682 else
ajs2a42e282004-12-08 18:43:03 +0000683 zlog_debug ("R %s\t%s\t%s\t%d",
paul718e3742002-12-13 20:15:29 +0000684 inet_ntop (AF_INET, &rn->p.u.prefix4, buf1, BUFSIZ),
685 inet_ntop (AF_INET, &or->u.std.area_id, buf2,
686 BUFSIZ),
687 ospf_path_type_str[or->path_type],
688 or->cost);
689 }
ajs2a42e282004-12-08 18:43:03 +0000690 zlog_debug ("========================================");
paul718e3742002-12-13 20:15:29 +0000691}
692
paul718e3742002-12-13 20:15:29 +0000693/* This is 16.4.1 implementation.
694 o Intra-area paths using non-backbone areas are always the most preferred.
695 o The other paths, intra-area backbone paths and inter-area paths,
696 are of equal preference. */
paul4dadc292005-05-06 21:37:42 +0000697static int
paul6d1fab62003-06-22 08:28:18 +0000698ospf_asbr_route_cmp (struct ospf *ospf, struct ospf_route *r1,
699 struct ospf_route *r2)
paul718e3742002-12-13 20:15:29 +0000700{
701 u_char r1_type, r2_type;
702
703 r1_type = r1->path_type;
704 r2_type = r2->path_type;
705
706 /* If RFC1583Compat flag is on -- all paths are equal. */
paul6d1fab62003-06-22 08:28:18 +0000707 if (CHECK_FLAG (ospf->config, OSPF_RFC1583_COMPATIBLE))
paul718e3742002-12-13 20:15:29 +0000708 return 0;
709
710 /* r1/r2 itself is backbone, and it's Inter-area path. */
711 if (OSPF_IS_AREA_ID_BACKBONE (r1->u.std.area_id))
712 r1_type = OSPF_PATH_INTER_AREA;
713 if (OSPF_IS_AREA_ID_BACKBONE (r2->u.std.area_id))
714 r2_type = OSPF_PATH_INTER_AREA;
715
716 return (r1_type - r2_type);
717}
718
719/* Compare two routes.
720 ret < 0 -- r1 is better.
721 ret == 0 -- r1 and r2 are the same.
722 ret > 0 -- r2 is better. */
723int
paul6d1fab62003-06-22 08:28:18 +0000724ospf_route_cmp (struct ospf *ospf, struct ospf_route *r1,
725 struct ospf_route *r2)
paul718e3742002-12-13 20:15:29 +0000726{
727 int ret = 0;
728
729 /* Path types of r1 and r2 are not the same. */
730 if ((ret = (r1->path_type - r2->path_type)))
731 return ret;
732
733 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000734 zlog_debug ("Route[Compare]: Path types are the same.");
paul718e3742002-12-13 20:15:29 +0000735 /* Path types are the same, compare any cost. */
736 switch (r1->path_type)
737 {
738 case OSPF_PATH_INTRA_AREA:
739 case OSPF_PATH_INTER_AREA:
740 break;
741 case OSPF_PATH_TYPE1_EXTERNAL:
paul6d1fab62003-06-22 08:28:18 +0000742 if (!CHECK_FLAG (ospf->config, OSPF_RFC1583_COMPATIBLE))
paul718e3742002-12-13 20:15:29 +0000743 {
paul6d1fab62003-06-22 08:28:18 +0000744 ret = ospf_asbr_route_cmp (ospf, r1->u.ext.asbr, r2->u.ext.asbr);
paul718e3742002-12-13 20:15:29 +0000745 if (ret != 0)
746 return ret;
747 }
748 break;
749 case OSPF_PATH_TYPE2_EXTERNAL:
750 if ((ret = (r1->u.ext.type2_cost - r2->u.ext.type2_cost)))
751 return ret;
752
paul6d1fab62003-06-22 08:28:18 +0000753 if (!CHECK_FLAG (ospf->config, OSPF_RFC1583_COMPATIBLE))
paul718e3742002-12-13 20:15:29 +0000754 {
paul6d1fab62003-06-22 08:28:18 +0000755 ret = ospf_asbr_route_cmp (ospf, r1->u.ext.asbr, r2->u.ext.asbr);
paul718e3742002-12-13 20:15:29 +0000756 if (ret != 0)
757 return ret;
758 }
759 break;
760 }
761
762 /* Anyway, compare the costs. */
763 return (r1->cost - r2->cost);
764}
765
paul4dadc292005-05-06 21:37:42 +0000766static int
paul718e3742002-12-13 20:15:29 +0000767ospf_path_exist (struct list *plist, struct in_addr nexthop,
768 struct ospf_interface *oi)
769{
paul1eb8ef22005-04-07 07:30:20 +0000770 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000771 struct ospf_path *path;
772
paul1eb8ef22005-04-07 07:30:20 +0000773 for (ALL_LIST_ELEMENTS (plist, node, nnode, path))
774 if (IPV4_ADDR_SAME (&path->nexthop, &nexthop) && path->oi == oi)
775 return 1;
paul718e3742002-12-13 20:15:29 +0000776
paul718e3742002-12-13 20:15:29 +0000777 return 0;
778}
779
780void
781ospf_route_copy_nexthops_from_vertex (struct ospf_route *to,
782 struct vertex *v)
783{
paul1eb8ef22005-04-07 07:30:20 +0000784 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000785 struct ospf_path *path;
786 struct vertex_nexthop *nexthop;
pauleb3da6d2005-10-18 04:20:33 +0000787 struct vertex_parent *vp;
paul718e3742002-12-13 20:15:29 +0000788
paul96735ee2003-08-10 02:51:22 +0000789 assert (to->paths);
paul718e3742002-12-13 20:15:29 +0000790
pauleb3da6d2005-10-18 04:20:33 +0000791 for (ALL_LIST_ELEMENTS_RO (v->parents, node, vp))
paul718e3742002-12-13 20:15:29 +0000792 {
pauleb3da6d2005-10-18 04:20:33 +0000793 nexthop = vp->nexthop;
794
paul718e3742002-12-13 20:15:29 +0000795 if (nexthop->oi != NULL)
796 {
paul96735ee2003-08-10 02:51:22 +0000797 if (! ospf_path_exist (to->paths, nexthop->router, nexthop->oi))
paul718e3742002-12-13 20:15:29 +0000798 {
799 path = ospf_path_new ();
800 path->nexthop = nexthop->router;
801 path->oi = nexthop->oi;
paul96735ee2003-08-10 02:51:22 +0000802 listnode_add (to->paths, path);
paul718e3742002-12-13 20:15:29 +0000803 }
804 }
805 }
806}
807
808struct ospf_path *
hasso52dc7ee2004-09-23 19:18:23 +0000809ospf_path_lookup (struct list *plist, struct ospf_path *path)
paul718e3742002-12-13 20:15:29 +0000810{
hasso52dc7ee2004-09-23 19:18:23 +0000811 struct listnode *node;
paul1eb8ef22005-04-07 07:30:20 +0000812 struct ospf_path *op;
paul718e3742002-12-13 20:15:29 +0000813
paul1eb8ef22005-04-07 07:30:20 +0000814 for (ALL_LIST_ELEMENTS_RO (plist, node, op))
815 if (IPV4_ADDR_SAME (&op->nexthop, &path->nexthop) &&
816 IPV4_ADDR_SAME (&op->adv_router, &path->adv_router))
817 return op;
paul718e3742002-12-13 20:15:29 +0000818
819 return NULL;
820}
821
822void
hasso52dc7ee2004-09-23 19:18:23 +0000823ospf_route_copy_nexthops (struct ospf_route *to, struct list *from)
paul718e3742002-12-13 20:15:29 +0000824{
paul1eb8ef22005-04-07 07:30:20 +0000825 struct listnode *node, *nnode;
826 struct ospf_path *path;
paul718e3742002-12-13 20:15:29 +0000827
paul96735ee2003-08-10 02:51:22 +0000828 assert (to->paths);
paul718e3742002-12-13 20:15:29 +0000829
paul1eb8ef22005-04-07 07:30:20 +0000830 for (ALL_LIST_ELEMENTS (from, node, nnode, path))
paul718e3742002-12-13 20:15:29 +0000831 /* The same routes are just discarded. */
paul1eb8ef22005-04-07 07:30:20 +0000832 if (!ospf_path_lookup (to->paths, path))
833 listnode_add (to->paths, ospf_path_dup (path));
paul718e3742002-12-13 20:15:29 +0000834}
835
836void
hasso52dc7ee2004-09-23 19:18:23 +0000837ospf_route_subst_nexthops (struct ospf_route *to, struct list *from)
paul718e3742002-12-13 20:15:29 +0000838{
paul718e3742002-12-13 20:15:29 +0000839
paul96735ee2003-08-10 02:51:22 +0000840 list_delete_all_node (to->paths);
paul718e3742002-12-13 20:15:29 +0000841 ospf_route_copy_nexthops (to, from);
842}
843
844void
845ospf_route_subst (struct route_node *rn, struct ospf_route *new_or,
846 struct ospf_route *over)
847{
848 route_lock_node (rn);
849 ospf_route_free (rn->info);
850
paul96735ee2003-08-10 02:51:22 +0000851 ospf_route_copy_nexthops (new_or, over->paths);
paul718e3742002-12-13 20:15:29 +0000852 rn->info = new_or;
853 route_unlock_node (rn);
854}
855
856void
857ospf_route_add (struct route_table *rt, struct prefix_ipv4 *p,
858 struct ospf_route *new_or, struct ospf_route *over)
859{
860 struct route_node *rn;
861
862 rn = route_node_get (rt, (struct prefix *) p);
863
paul96735ee2003-08-10 02:51:22 +0000864 ospf_route_copy_nexthops (new_or, over->paths);
paul718e3742002-12-13 20:15:29 +0000865
866 if (rn->info)
867 {
868 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000869 zlog_debug ("ospf_route_add(): something's wrong !");
paul718e3742002-12-13 20:15:29 +0000870 route_unlock_node (rn);
871 return;
872 }
873
874 rn->info = new_or;
875}
876
877void
878ospf_prune_unreachable_networks (struct route_table *rt)
879{
880 struct route_node *rn, *next;
881 struct ospf_route *or;
882
883 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000884 zlog_debug ("Pruning unreachable networks");
paul718e3742002-12-13 20:15:29 +0000885
886 for (rn = route_top (rt); rn; rn = next)
887 {
888 next = route_next (rn);
889 if (rn->info != NULL)
890 {
891 or = rn->info;
paul96735ee2003-08-10 02:51:22 +0000892 if (listcount (or->paths) == 0)
paul718e3742002-12-13 20:15:29 +0000893 {
894 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000895 zlog_debug ("Pruning route to %s/%d",
paul718e3742002-12-13 20:15:29 +0000896 inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen);
897
898 ospf_route_free (or);
899 rn->info = NULL;
900 route_unlock_node (rn);
901 }
902 }
903 }
904}
905
906void
907ospf_prune_unreachable_routers (struct route_table *rtrs)
908{
909 struct route_node *rn, *next;
910 struct ospf_route *or;
paul1eb8ef22005-04-07 07:30:20 +0000911 struct listnode *node, *nnode;
hasso52dc7ee2004-09-23 19:18:23 +0000912 struct list *paths;
paul718e3742002-12-13 20:15:29 +0000913
914 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000915 zlog_debug ("Pruning unreachable routers");
paul718e3742002-12-13 20:15:29 +0000916
917 for (rn = route_top (rtrs); rn; rn = next)
918 {
919 next = route_next (rn);
920 if ((paths = rn->info) == NULL)
921 continue;
922
paul1eb8ef22005-04-07 07:30:20 +0000923 for (ALL_LIST_ELEMENTS (paths, node, nnode, or))
paul718e3742002-12-13 20:15:29 +0000924 {
paul96735ee2003-08-10 02:51:22 +0000925 if (listcount (or->paths) == 0)
paul718e3742002-12-13 20:15:29 +0000926 {
927 if (IS_DEBUG_OSPF_EVENT)
928 {
ajs2a42e282004-12-08 18:43:03 +0000929 zlog_debug ("Pruning route to rtr %s",
paul718e3742002-12-13 20:15:29 +0000930 inet_ntoa (rn->p.u.prefix4));
ajs2a42e282004-12-08 18:43:03 +0000931 zlog_debug (" via area %s",
paul718e3742002-12-13 20:15:29 +0000932 inet_ntoa (or->u.std.area_id));
933 }
934
935 listnode_delete (paths, or);
936 ospf_route_free (or);
937 }
938 }
939
940 if (listcount (paths) == 0)
941 {
942 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000943 zlog_debug ("Pruning router node %s", inet_ntoa (rn->p.u.prefix4));
paul718e3742002-12-13 20:15:29 +0000944
945 list_delete (paths);
946 rn->info = NULL;
947 route_unlock_node (rn);
948 }
949 }
950}
951
952int
953ospf_add_discard_route (struct route_table *rt, struct ospf_area *area,
954 struct prefix_ipv4 *p)
955{
956 struct route_node *rn;
957 struct ospf_route *or, *new_or;
958
959 rn = route_node_get (rt, (struct prefix *) p);
960
961 if (rn == NULL)
962 {
963 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000964 zlog_debug ("ospf_add_discard_route(): router installation error");
paul718e3742002-12-13 20:15:29 +0000965 return 0;
966 }
967
968 if (rn->info) /* If the route to the same destination is found */
969 {
970 route_unlock_node (rn);
971
972 or = rn->info;
973
974 if (or->path_type == OSPF_PATH_INTRA_AREA)
975 {
976 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000977 zlog_debug ("ospf_add_discard_route(): "
paul718e3742002-12-13 20:15:29 +0000978 "an intra-area route exists");
979 return 0;
980 }
981
982 if (or->type == OSPF_DESTINATION_DISCARD)
983 {
984 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000985 zlog_debug ("ospf_add_discard_route(): "
paul718e3742002-12-13 20:15:29 +0000986 "discard entry already installed");
987 return 0;
988 }
989
990 ospf_route_free (rn->info);
991 }
992
993 new_or = ospf_route_new ();
994 new_or->type = OSPF_DESTINATION_DISCARD;
995 new_or->id.s_addr = 0;
996 new_or->cost = 0;
997 new_or->u.std.area_id = area->area_id;
paul718e3742002-12-13 20:15:29 +0000998 new_or->u.std.external_routing = area->external_routing;
paul718e3742002-12-13 20:15:29 +0000999 new_or->path_type = OSPF_PATH_INTER_AREA;
1000 rn->info = new_or;
1001
1002 ospf_zebra_add_discard (p);
1003
1004 return 1;
1005}
1006
1007void
1008ospf_delete_discard_route (struct prefix_ipv4 *p)
1009{
1010 ospf_zebra_delete_discard(p);
1011}
1012