blob: bdbdd03ea8184430ec98a7a1489d5fc42fc29bb2 [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
693void
694ospf_terminate ()
695{
paul6d1fab62003-06-22 08:28:18 +0000696 struct ospf *ospf;
paul1eb8ef22005-04-07 07:30:20 +0000697 struct listnode *node, *nnode;
paul6d1fab62003-06-22 08:28:18 +0000698
paul1eb8ef22005-04-07 07:30:20 +0000699 for (ALL_LIST_ELEMENTS (om->ospf, node, nnode, ospf))
paul718e3742002-12-13 20:15:29 +0000700 {
paul6d1fab62003-06-22 08:28:18 +0000701 if (ospf->new_table)
702 ospf_route_delete (ospf->new_table);
703 if (ospf->old_external_route)
704 ospf_route_delete (ospf->old_external_route);
paul718e3742002-12-13 20:15:29 +0000705 }
706}
707
708/* This is 16.4.1 implementation.
709 o Intra-area paths using non-backbone areas are always the most preferred.
710 o The other paths, intra-area backbone paths and inter-area paths,
711 are of equal preference. */
paul4dadc292005-05-06 21:37:42 +0000712static int
paul6d1fab62003-06-22 08:28:18 +0000713ospf_asbr_route_cmp (struct ospf *ospf, struct ospf_route *r1,
714 struct ospf_route *r2)
paul718e3742002-12-13 20:15:29 +0000715{
716 u_char r1_type, r2_type;
717
718 r1_type = r1->path_type;
719 r2_type = r2->path_type;
720
721 /* If RFC1583Compat flag is on -- all paths are equal. */
paul6d1fab62003-06-22 08:28:18 +0000722 if (CHECK_FLAG (ospf->config, OSPF_RFC1583_COMPATIBLE))
paul718e3742002-12-13 20:15:29 +0000723 return 0;
724
725 /* r1/r2 itself is backbone, and it's Inter-area path. */
726 if (OSPF_IS_AREA_ID_BACKBONE (r1->u.std.area_id))
727 r1_type = OSPF_PATH_INTER_AREA;
728 if (OSPF_IS_AREA_ID_BACKBONE (r2->u.std.area_id))
729 r2_type = OSPF_PATH_INTER_AREA;
730
731 return (r1_type - r2_type);
732}
733
734/* Compare two routes.
735 ret < 0 -- r1 is better.
736 ret == 0 -- r1 and r2 are the same.
737 ret > 0 -- r2 is better. */
738int
paul6d1fab62003-06-22 08:28:18 +0000739ospf_route_cmp (struct ospf *ospf, struct ospf_route *r1,
740 struct ospf_route *r2)
paul718e3742002-12-13 20:15:29 +0000741{
742 int ret = 0;
743
744 /* Path types of r1 and r2 are not the same. */
745 if ((ret = (r1->path_type - r2->path_type)))
746 return ret;
747
748 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000749 zlog_debug ("Route[Compare]: Path types are the same.");
paul718e3742002-12-13 20:15:29 +0000750 /* Path types are the same, compare any cost. */
751 switch (r1->path_type)
752 {
753 case OSPF_PATH_INTRA_AREA:
754 case OSPF_PATH_INTER_AREA:
755 break;
756 case OSPF_PATH_TYPE1_EXTERNAL:
paul6d1fab62003-06-22 08:28:18 +0000757 if (!CHECK_FLAG (ospf->config, OSPF_RFC1583_COMPATIBLE))
paul718e3742002-12-13 20:15:29 +0000758 {
paul6d1fab62003-06-22 08:28:18 +0000759 ret = ospf_asbr_route_cmp (ospf, r1->u.ext.asbr, r2->u.ext.asbr);
paul718e3742002-12-13 20:15:29 +0000760 if (ret != 0)
761 return ret;
762 }
763 break;
764 case OSPF_PATH_TYPE2_EXTERNAL:
765 if ((ret = (r1->u.ext.type2_cost - r2->u.ext.type2_cost)))
766 return ret;
767
paul6d1fab62003-06-22 08:28:18 +0000768 if (!CHECK_FLAG (ospf->config, OSPF_RFC1583_COMPATIBLE))
paul718e3742002-12-13 20:15:29 +0000769 {
paul6d1fab62003-06-22 08:28:18 +0000770 ret = ospf_asbr_route_cmp (ospf, r1->u.ext.asbr, r2->u.ext.asbr);
paul718e3742002-12-13 20:15:29 +0000771 if (ret != 0)
772 return ret;
773 }
774 break;
775 }
776
777 /* Anyway, compare the costs. */
778 return (r1->cost - r2->cost);
779}
780
paul4dadc292005-05-06 21:37:42 +0000781static int
paul718e3742002-12-13 20:15:29 +0000782ospf_path_exist (struct list *plist, struct in_addr nexthop,
783 struct ospf_interface *oi)
784{
paul1eb8ef22005-04-07 07:30:20 +0000785 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000786 struct ospf_path *path;
787
paul1eb8ef22005-04-07 07:30:20 +0000788 for (ALL_LIST_ELEMENTS (plist, node, nnode, path))
789 if (IPV4_ADDR_SAME (&path->nexthop, &nexthop) && path->oi == oi)
790 return 1;
paul718e3742002-12-13 20:15:29 +0000791
paul718e3742002-12-13 20:15:29 +0000792 return 0;
793}
794
795void
796ospf_route_copy_nexthops_from_vertex (struct ospf_route *to,
797 struct vertex *v)
798{
paul1eb8ef22005-04-07 07:30:20 +0000799 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000800 struct ospf_path *path;
801 struct vertex_nexthop *nexthop;
pauleb3da6d2005-10-18 04:20:33 +0000802 struct vertex_parent *vp;
paul718e3742002-12-13 20:15:29 +0000803
paul96735ee2003-08-10 02:51:22 +0000804 assert (to->paths);
paul718e3742002-12-13 20:15:29 +0000805
pauleb3da6d2005-10-18 04:20:33 +0000806 for (ALL_LIST_ELEMENTS_RO (v->parents, node, vp))
paul718e3742002-12-13 20:15:29 +0000807 {
pauleb3da6d2005-10-18 04:20:33 +0000808 nexthop = vp->nexthop;
809
paul718e3742002-12-13 20:15:29 +0000810 if (nexthop->oi != NULL)
811 {
paul96735ee2003-08-10 02:51:22 +0000812 if (! ospf_path_exist (to->paths, nexthop->router, nexthop->oi))
paul718e3742002-12-13 20:15:29 +0000813 {
814 path = ospf_path_new ();
815 path->nexthop = nexthop->router;
816 path->oi = nexthop->oi;
paul96735ee2003-08-10 02:51:22 +0000817 listnode_add (to->paths, path);
paul718e3742002-12-13 20:15:29 +0000818 }
819 }
820 }
821}
822
823struct ospf_path *
hasso52dc7ee2004-09-23 19:18:23 +0000824ospf_path_lookup (struct list *plist, struct ospf_path *path)
paul718e3742002-12-13 20:15:29 +0000825{
hasso52dc7ee2004-09-23 19:18:23 +0000826 struct listnode *node;
paul1eb8ef22005-04-07 07:30:20 +0000827 struct ospf_path *op;
paul718e3742002-12-13 20:15:29 +0000828
paul1eb8ef22005-04-07 07:30:20 +0000829 for (ALL_LIST_ELEMENTS_RO (plist, node, op))
830 if (IPV4_ADDR_SAME (&op->nexthop, &path->nexthop) &&
831 IPV4_ADDR_SAME (&op->adv_router, &path->adv_router))
832 return op;
paul718e3742002-12-13 20:15:29 +0000833
834 return NULL;
835}
836
837void
hasso52dc7ee2004-09-23 19:18:23 +0000838ospf_route_copy_nexthops (struct ospf_route *to, struct list *from)
paul718e3742002-12-13 20:15:29 +0000839{
paul1eb8ef22005-04-07 07:30:20 +0000840 struct listnode *node, *nnode;
841 struct ospf_path *path;
paul718e3742002-12-13 20:15:29 +0000842
paul96735ee2003-08-10 02:51:22 +0000843 assert (to->paths);
paul718e3742002-12-13 20:15:29 +0000844
paul1eb8ef22005-04-07 07:30:20 +0000845 for (ALL_LIST_ELEMENTS (from, node, nnode, path))
paul718e3742002-12-13 20:15:29 +0000846 /* The same routes are just discarded. */
paul1eb8ef22005-04-07 07:30:20 +0000847 if (!ospf_path_lookup (to->paths, path))
848 listnode_add (to->paths, ospf_path_dup (path));
paul718e3742002-12-13 20:15:29 +0000849}
850
851void
hasso52dc7ee2004-09-23 19:18:23 +0000852ospf_route_subst_nexthops (struct ospf_route *to, struct list *from)
paul718e3742002-12-13 20:15:29 +0000853{
paul718e3742002-12-13 20:15:29 +0000854
paul96735ee2003-08-10 02:51:22 +0000855 list_delete_all_node (to->paths);
paul718e3742002-12-13 20:15:29 +0000856 ospf_route_copy_nexthops (to, from);
857}
858
859void
860ospf_route_subst (struct route_node *rn, struct ospf_route *new_or,
861 struct ospf_route *over)
862{
863 route_lock_node (rn);
864 ospf_route_free (rn->info);
865
paul96735ee2003-08-10 02:51:22 +0000866 ospf_route_copy_nexthops (new_or, over->paths);
paul718e3742002-12-13 20:15:29 +0000867 rn->info = new_or;
868 route_unlock_node (rn);
869}
870
871void
872ospf_route_add (struct route_table *rt, struct prefix_ipv4 *p,
873 struct ospf_route *new_or, struct ospf_route *over)
874{
875 struct route_node *rn;
876
877 rn = route_node_get (rt, (struct prefix *) p);
878
paul96735ee2003-08-10 02:51:22 +0000879 ospf_route_copy_nexthops (new_or, over->paths);
paul718e3742002-12-13 20:15:29 +0000880
881 if (rn->info)
882 {
883 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000884 zlog_debug ("ospf_route_add(): something's wrong !");
paul718e3742002-12-13 20:15:29 +0000885 route_unlock_node (rn);
886 return;
887 }
888
889 rn->info = new_or;
890}
891
892void
893ospf_prune_unreachable_networks (struct route_table *rt)
894{
895 struct route_node *rn, *next;
896 struct ospf_route *or;
897
898 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000899 zlog_debug ("Pruning unreachable networks");
paul718e3742002-12-13 20:15:29 +0000900
901 for (rn = route_top (rt); rn; rn = next)
902 {
903 next = route_next (rn);
904 if (rn->info != NULL)
905 {
906 or = rn->info;
paul96735ee2003-08-10 02:51:22 +0000907 if (listcount (or->paths) == 0)
paul718e3742002-12-13 20:15:29 +0000908 {
909 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000910 zlog_debug ("Pruning route to %s/%d",
paul718e3742002-12-13 20:15:29 +0000911 inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen);
912
913 ospf_route_free (or);
914 rn->info = NULL;
915 route_unlock_node (rn);
916 }
917 }
918 }
919}
920
921void
922ospf_prune_unreachable_routers (struct route_table *rtrs)
923{
924 struct route_node *rn, *next;
925 struct ospf_route *or;
paul1eb8ef22005-04-07 07:30:20 +0000926 struct listnode *node, *nnode;
hasso52dc7ee2004-09-23 19:18:23 +0000927 struct list *paths;
paul718e3742002-12-13 20:15:29 +0000928
929 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000930 zlog_debug ("Pruning unreachable routers");
paul718e3742002-12-13 20:15:29 +0000931
932 for (rn = route_top (rtrs); rn; rn = next)
933 {
934 next = route_next (rn);
935 if ((paths = rn->info) == NULL)
936 continue;
937
paul1eb8ef22005-04-07 07:30:20 +0000938 for (ALL_LIST_ELEMENTS (paths, node, nnode, or))
paul718e3742002-12-13 20:15:29 +0000939 {
paul96735ee2003-08-10 02:51:22 +0000940 if (listcount (or->paths) == 0)
paul718e3742002-12-13 20:15:29 +0000941 {
942 if (IS_DEBUG_OSPF_EVENT)
943 {
ajs2a42e282004-12-08 18:43:03 +0000944 zlog_debug ("Pruning route to rtr %s",
paul718e3742002-12-13 20:15:29 +0000945 inet_ntoa (rn->p.u.prefix4));
ajs2a42e282004-12-08 18:43:03 +0000946 zlog_debug (" via area %s",
paul718e3742002-12-13 20:15:29 +0000947 inet_ntoa (or->u.std.area_id));
948 }
949
950 listnode_delete (paths, or);
951 ospf_route_free (or);
952 }
953 }
954
955 if (listcount (paths) == 0)
956 {
957 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000958 zlog_debug ("Pruning router node %s", inet_ntoa (rn->p.u.prefix4));
paul718e3742002-12-13 20:15:29 +0000959
960 list_delete (paths);
961 rn->info = NULL;
962 route_unlock_node (rn);
963 }
964 }
965}
966
967int
968ospf_add_discard_route (struct route_table *rt, struct ospf_area *area,
969 struct prefix_ipv4 *p)
970{
971 struct route_node *rn;
972 struct ospf_route *or, *new_or;
973
974 rn = route_node_get (rt, (struct prefix *) p);
975
976 if (rn == NULL)
977 {
978 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000979 zlog_debug ("ospf_add_discard_route(): router installation error");
paul718e3742002-12-13 20:15:29 +0000980 return 0;
981 }
982
983 if (rn->info) /* If the route to the same destination is found */
984 {
985 route_unlock_node (rn);
986
987 or = rn->info;
988
989 if (or->path_type == OSPF_PATH_INTRA_AREA)
990 {
991 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000992 zlog_debug ("ospf_add_discard_route(): "
paul718e3742002-12-13 20:15:29 +0000993 "an intra-area route exists");
994 return 0;
995 }
996
997 if (or->type == OSPF_DESTINATION_DISCARD)
998 {
999 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001000 zlog_debug ("ospf_add_discard_route(): "
paul718e3742002-12-13 20:15:29 +00001001 "discard entry already installed");
1002 return 0;
1003 }
1004
1005 ospf_route_free (rn->info);
1006 }
1007
1008 new_or = ospf_route_new ();
1009 new_or->type = OSPF_DESTINATION_DISCARD;
1010 new_or->id.s_addr = 0;
1011 new_or->cost = 0;
1012 new_or->u.std.area_id = area->area_id;
paul718e3742002-12-13 20:15:29 +00001013 new_or->u.std.external_routing = area->external_routing;
paul718e3742002-12-13 20:15:29 +00001014 new_or->path_type = OSPF_PATH_INTER_AREA;
1015 rn->info = new_or;
1016
1017 ospf_zebra_add_discard (p);
1018
1019 return 1;
1020}
1021
1022void
1023ospf_delete_discard_route (struct prefix_ipv4 *p)
1024{
1025 ospf_zebra_delete_discard(p);
1026}
1027