blob: d2e5e1e7d00e19fa16fe01c4afb493f9d8adf17d [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/*
2 * OSPF routing table.
3 * Copyright (C) 1999, 2000 Toshiaki Takada
4 *
5 * This file is part of GNU Zebra.
6 *
7 * GNU Zebra is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
10 * later version.
11 *
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with GNU Zebra; see the file COPYING. If not, write to the Free
19 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20 * 02111-1307, USA.
21 */
22
23#include <zebra.h>
24
25#include "prefix.h"
26#include "table.h"
27#include "memory.h"
28#include "linklist.h"
29#include "log.h"
30#include "if.h"
31#include "command.h"
32#include "sockunion.h"
33
34#include "ospfd/ospfd.h"
35#include "ospfd/ospf_interface.h"
36#include "ospfd/ospf_asbr.h"
37#include "ospfd/ospf_lsa.h"
38#include "ospfd/ospf_route.h"
39#include "ospfd/ospf_spf.h"
40#include "ospfd/ospf_zebra.h"
41#include "ospfd/ospf_dump.h"
42
43struct ospf_route *
44ospf_route_new ()
45{
46 struct ospf_route *new;
47
48 new = XCALLOC (MTYPE_OSPF_ROUTE, sizeof (struct ospf_route));
49
Paul Jakma2518efd2006-08-27 06:49:29 +000050 new->ctime = quagga_time (NULL);
paul718e3742002-12-13 20:15:29 +000051 new->mtime = new->ctime;
paul96735ee2003-08-10 02:51:22 +000052 new->paths = list_new ();
53 new->paths->del = (void (*) (void *))ospf_path_free;
paul718e3742002-12-13 20:15:29 +000054
55 return new;
56}
57
58void
59ospf_route_free (struct ospf_route *or)
60{
paul96735ee2003-08-10 02:51:22 +000061 if (or->paths)
62 list_delete (or->paths);
paul718e3742002-12-13 20:15:29 +000063
64 XFREE (MTYPE_OSPF_ROUTE, or);
65}
66
67struct ospf_path *
68ospf_path_new ()
69{
70 struct ospf_path *new;
71
72 new = XCALLOC (MTYPE_OSPF_PATH, sizeof (struct ospf_path));
73
74 return new;
75}
76
paul4dadc292005-05-06 21:37:42 +000077static struct ospf_path *
paul718e3742002-12-13 20:15:29 +000078ospf_path_dup (struct ospf_path *path)
79{
80 struct ospf_path *new;
81
82 new = ospf_path_new ();
83 memcpy (new, path, sizeof (struct ospf_path));
84
85 return new;
86}
87
88void
89ospf_path_free (struct ospf_path *op)
90{
91 XFREE (MTYPE_OSPF_PATH, op);
92}
93
94void
95ospf_route_delete (struct route_table *rt)
96{
97 struct route_node *rn;
98 struct ospf_route *or;
99
100 for (rn = route_top (rt); rn; rn = route_next (rn))
101 if ((or = rn->info) != NULL)
102 {
103 if (or->type == OSPF_DESTINATION_NETWORK)
104 ospf_zebra_delete ((struct prefix_ipv4 *) &rn->p,
105 or);
106 else if (or->type == OSPF_DESTINATION_DISCARD)
107 ospf_zebra_delete_discard ((struct prefix_ipv4 *) &rn->p);
108 }
109}
110
111void
112ospf_route_table_free (struct route_table *rt)
113{
114 struct route_node *rn;
115 struct ospf_route *or;
116
117 for (rn = route_top (rt); rn; rn = route_next (rn))
118 if ((or = rn->info) != NULL)
119 {
120 ospf_route_free (or);
121
122 rn->info = NULL;
123 route_unlock_node (rn);
124 }
125
126 route_table_finish (rt);
127}
128
129/* If a prefix and a nexthop match any route in the routing table,
130 then return 1, otherwise return 0. */
131int
132ospf_route_match_same (struct route_table *rt, struct prefix_ipv4 *prefix,
133 struct ospf_route *newor)
134{
135 struct route_node *rn;
136 struct ospf_route *or;
137 struct ospf_path *op;
138 struct ospf_path *newop;
hasso52dc7ee2004-09-23 19:18:23 +0000139 struct listnode *n1;
140 struct listnode *n2;
paul718e3742002-12-13 20:15:29 +0000141
142 if (! rt || ! prefix)
143 return 0;
144
145 rn = route_node_lookup (rt, (struct prefix *) prefix);
146 if (! rn || ! rn->info)
147 return 0;
148
149 route_unlock_node (rn);
150
151 or = rn->info;
152 if (or->type == newor->type && or->cost == newor->cost)
153 {
154 if (or->type == OSPF_DESTINATION_NETWORK)
155 {
paul96735ee2003-08-10 02:51:22 +0000156 if (or->paths->count != newor->paths->count)
paul718e3742002-12-13 20:15:29 +0000157 return 0;
158
159 /* Check each path. */
paul96735ee2003-08-10 02:51:22 +0000160 for (n1 = listhead (or->paths), n2 = listhead (newor->paths);
paul1eb8ef22005-04-07 07:30:20 +0000161 n1 && n2; n1 = listnextnode (n1), n2 = listnextnode (n2))
paul718e3742002-12-13 20:15:29 +0000162 {
paul1eb8ef22005-04-07 07:30:20 +0000163 op = listgetdata (n1);
164 newop = listgetdata (n2);
paul718e3742002-12-13 20:15:29 +0000165
166 if (! IPV4_ADDR_SAME (&op->nexthop, &newop->nexthop))
167 return 0;
Joakim Tjernlunda8ba8472009-07-27 12:42:34 +0200168 if (op->ifindex != newop->ifindex)
Joakim Tjernlund77a1c4e2009-02-01 11:12:11 +0100169 return 0;
paul718e3742002-12-13 20:15:29 +0000170 }
171 return 1;
172 }
173 else if (prefix_same (&rn->p, (struct prefix *) prefix))
174 return 1;
175 }
176 return 0;
177}
178
paul6d1fab62003-06-22 08:28:18 +0000179/* delete routes generated from AS-External routes if there is a inter/intra
180 * area route
181 */
paul4dadc292005-05-06 21:37:42 +0000182static void
paul6d1fab62003-06-22 08:28:18 +0000183ospf_route_delete_same_ext(struct route_table *external_routes,
184 struct route_table *routes)
185{
186 struct route_node *rn,
187 *ext_rn;
188
189 if ( (external_routes == NULL) || (routes == NULL) )
190 return;
191
192 /* Remove deleted routes */
193 for ( rn = route_top (routes); rn; rn = route_next (rn) )
194 {
195 if (rn && rn->info)
196 {
hassofa2b17e2004-03-04 17:45:00 +0000197 struct prefix_ipv4 *p = (struct prefix_ipv4 *)(&rn->p);
198 if ( (ext_rn = route_node_lookup (external_routes, (struct prefix *)p)) )
paul6d1fab62003-06-22 08:28:18 +0000199 {
paul6d1fab62003-06-22 08:28:18 +0000200 if (ext_rn->info)
201 {
Paul Jakma894f8b62006-05-12 22:50:40 +0000202 ospf_zebra_delete (p, ext_rn->info);
paul6d1fab62003-06-22 08:28:18 +0000203 ospf_route_free( ext_rn->info);
204 ext_rn->info = NULL;
205 }
206 route_unlock_node (ext_rn);
207 }
208 }
209 }
210}
211
paul718e3742002-12-13 20:15:29 +0000212/* rt: Old, cmprt: New */
paul4dadc292005-05-06 21:37:42 +0000213static void
paul718e3742002-12-13 20:15:29 +0000214ospf_route_delete_uniq (struct route_table *rt, struct route_table *cmprt)
215{
216 struct route_node *rn;
217 struct ospf_route *or;
218
219 for (rn = route_top (rt); rn; rn = route_next (rn))
220 if ((or = rn->info) != NULL)
221 if (or->path_type == OSPF_PATH_INTRA_AREA ||
222 or->path_type == OSPF_PATH_INTER_AREA)
223 {
224 if (or->type == OSPF_DESTINATION_NETWORK)
225 {
226 if (! ospf_route_match_same (cmprt,
227 (struct prefix_ipv4 *) &rn->p, or))
228 ospf_zebra_delete ((struct prefix_ipv4 *) &rn->p, or);
229 }
230 else if (or->type == OSPF_DESTINATION_DISCARD)
231 if (! ospf_route_match_same (cmprt,
232 (struct prefix_ipv4 *) &rn->p, or))
233 ospf_zebra_delete_discard ((struct prefix_ipv4 *) &rn->p);
234 }
235}
236
237/* Install routes to table. */
238void
paul6d1fab62003-06-22 08:28:18 +0000239ospf_route_install (struct ospf *ospf, struct route_table *rt)
paul718e3742002-12-13 20:15:29 +0000240{
241 struct route_node *rn;
242 struct ospf_route *or;
243
244 /* rt contains new routing table, new_table contains an old one.
245 updating pointers */
paul6d1fab62003-06-22 08:28:18 +0000246 if (ospf->old_table)
247 ospf_route_table_free (ospf->old_table);
248
249 ospf->old_table = ospf->new_table;
250 ospf->new_table = rt;
paul718e3742002-12-13 20:15:29 +0000251
252 /* Delete old routes. */
paul6d1fab62003-06-22 08:28:18 +0000253 if (ospf->old_table)
254 ospf_route_delete_uniq (ospf->old_table, rt);
255 if (ospf->old_external_route)
256 ospf_route_delete_same_ext (ospf->old_external_route, rt);
paul718e3742002-12-13 20:15:29 +0000257
258 /* Install new routes. */
259 for (rn = route_top (rt); rn; rn = route_next (rn))
260 if ((or = rn->info) != NULL)
261 {
262 if (or->type == OSPF_DESTINATION_NETWORK)
263 {
paul6d1fab62003-06-22 08:28:18 +0000264 if (! ospf_route_match_same (ospf->old_table,
paul718e3742002-12-13 20:15:29 +0000265 (struct prefix_ipv4 *)&rn->p, or))
266 ospf_zebra_add ((struct prefix_ipv4 *) &rn->p, or);
267 }
268 else if (or->type == OSPF_DESTINATION_DISCARD)
paul6d1fab62003-06-22 08:28:18 +0000269 if (! ospf_route_match_same (ospf->old_table,
paul718e3742002-12-13 20:15:29 +0000270 (struct prefix_ipv4 *) &rn->p, or))
271 ospf_zebra_add_discard ((struct prefix_ipv4 *) &rn->p);
272 }
273}
274
paul718e3742002-12-13 20:15:29 +0000275/* RFC2328 16.1. (4). For "router". */
276void
277ospf_intra_add_router (struct route_table *rt, struct vertex *v,
278 struct ospf_area *area)
279{
280 struct route_node *rn;
281 struct ospf_route *or;
282 struct prefix_ipv4 p;
283 struct router_lsa *lsa;
284
285 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000286 zlog_debug ("ospf_intra_add_router: Start");
paul718e3742002-12-13 20:15:29 +0000287
288 lsa = (struct router_lsa *) v->lsa;
289
290 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000291 zlog_debug ("ospf_intra_add_router: LS ID: %s",
paul718e3742002-12-13 20:15:29 +0000292 inet_ntoa (lsa->header.id));
Paul Jakma9c27ef92006-05-04 07:32:57 +0000293
294 if (!OSPF_IS_AREA_BACKBONE(area))
295 ospf_vl_up_check (area, lsa->header.id, v);
paul718e3742002-12-13 20:15:29 +0000296
297 if (!CHECK_FLAG (lsa->flags, ROUTER_LSA_SHORTCUT))
298 area->shortcut_capability = 0;
299
300 /* If the newly added vertex is an area border router or AS boundary
301 router, a routing table entry is added whose destination type is
302 "router". */
303 if (! IS_ROUTER_LSA_BORDER (lsa) && ! IS_ROUTER_LSA_EXTERNAL (lsa))
304 {
305 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000306 zlog_debug ("ospf_intra_add_router: "
paul718e3742002-12-13 20:15:29 +0000307 "this router is neither ASBR nor ABR, skipping it");
308 return;
309 }
310
311 /* Update ABR and ASBR count in this area. */
312 if (IS_ROUTER_LSA_BORDER (lsa))
313 area->abr_count++;
314 if (IS_ROUTER_LSA_EXTERNAL (lsa))
315 area->asbr_count++;
316
317 /* The Options field found in the associated router-LSA is copied
318 into the routing table entry's Optional capabilities field. Call
319 the newly added vertex Router X. */
320 or = ospf_route_new ();
321
322 or->id = v->id;
323 or->u.std.area_id = area->area_id;
paul718e3742002-12-13 20:15:29 +0000324 or->u.std.external_routing = area->external_routing;
paul718e3742002-12-13 20:15:29 +0000325 or->path_type = OSPF_PATH_INTRA_AREA;
326 or->cost = v->distance;
327 or->type = OSPF_DESTINATION_ROUTER;
328 or->u.std.origin = (struct lsa_header *) lsa;
329 or->u.std.options = lsa->header.options;
330 or->u.std.flags = lsa->flags;
331
332 /* If Router X is the endpoint of one of the calculating router's
333 virtual links, and the virtual link uses Area A as Transit area:
334 the virtual link is declared up, the IP address of the virtual
335 interface is set to the IP address of the outgoing interface
336 calculated above for Router X, and the virtual neighbor's IP
337 address is set to Router X's interface address (contained in
338 Router X's router-LSA) that points back to the root of the
339 shortest- path tree; equivalently, this is the interface that
340 points back to Router X's parent vertex on the shortest-path tree
341 (similar to the calculation in Section 16.1.1). */
342
343 p.family = AF_INET;
344 p.prefix = v->id;
345 p.prefixlen = IPV4_MAX_BITLEN;
346
347 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000348 zlog_debug ("ospf_intra_add_router: talking about %s/%d",
paul718e3742002-12-13 20:15:29 +0000349 inet_ntoa (p.prefix), p.prefixlen);
350
351 rn = route_node_get (rt, (struct prefix *) &p);
352
353 /* Note that we keep all routes to ABRs and ASBRs, not only the best */
354 if (rn->info == NULL)
355 rn->info = list_new ();
356 else
357 route_unlock_node (rn);
358
359 ospf_route_copy_nexthops_from_vertex (or, v);
360
361 listnode_add (rn->info, or);
362
hasso9e1be242004-04-20 03:50:59 +0000363 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000364 zlog_debug ("ospf_intra_add_router: Stop");
paul718e3742002-12-13 20:15:29 +0000365}
366
367/* RFC2328 16.1. (4). For transit network. */
368void
369ospf_intra_add_transit (struct route_table *rt, struct vertex *v,
370 struct ospf_area *area)
371{
372 struct route_node *rn;
373 struct ospf_route *or;
374 struct prefix_ipv4 p;
375 struct network_lsa *lsa;
376
377 lsa = (struct network_lsa*) v->lsa;
378
379 /* If the newly added vertex is a transit network, the routing table
380 entry for the network is located. The entry's Destination ID is
381 the IP network number, which can be obtained by masking the
382 Vertex ID (Link State ID) with its associated subnet mask (found
383 in the body of the associated network-LSA). */
384 p.family = AF_INET;
385 p.prefix = v->id;
386 p.prefixlen = ip_masklen (lsa->mask);
387 apply_mask_ipv4 (&p);
388
389 rn = route_node_get (rt, (struct prefix *) &p);
390
391 /* If the routing table entry already exists (i.e., there is already
392 an intra-area route to the destination installed in the routing
393 table), multiple vertices have mapped to the same IP network.
394 For example, this can occur when a new Designated Router is being
395 established. In this case, the current routing table entry
396 should be overwritten if and only if the newly found path is just
397 as short and the current routing table entry's Link State Origin
398 has a smaller Link State ID than the newly added vertex' LSA. */
399 if (rn->info)
400 {
401 struct ospf_route *cur_or;
402
403 route_unlock_node (rn);
404 cur_or = rn->info;
405
406 if (v->distance > cur_or->cost ||
407 IPV4_ADDR_CMP (&cur_or->u.std.origin->id, &lsa->header.id) > 0)
408 return;
409
410 ospf_route_free (rn->info);
411 }
412
413 or = ospf_route_new ();
414
415 or->id = v->id;
416 or->u.std.area_id = area->area_id;
paul718e3742002-12-13 20:15:29 +0000417 or->u.std.external_routing = area->external_routing;
paul718e3742002-12-13 20:15:29 +0000418 or->path_type = OSPF_PATH_INTRA_AREA;
419 or->cost = v->distance;
420 or->type = OSPF_DESTINATION_NETWORK;
421 or->u.std.origin = (struct lsa_header *) lsa;
422
423 ospf_route_copy_nexthops_from_vertex (or, v);
424
425 rn->info = or;
426}
427
428/* RFC2328 16.1. second stage. */
429void
430ospf_intra_add_stub (struct route_table *rt, struct router_lsa_link *link,
Paul Jakmab3bc68e2008-09-04 13:52:07 +0100431 struct vertex *v, struct ospf_area *area,
432 int parent_is_root)
paul718e3742002-12-13 20:15:29 +0000433{
434 u_int32_t cost;
435 struct route_node *rn;
436 struct ospf_route *or;
437 struct prefix_ipv4 p;
438 struct router_lsa *lsa;
439 struct ospf_interface *oi;
440 struct ospf_path *path;
441
442 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000443 zlog_debug ("ospf_intra_add_stub(): Start");
paul718e3742002-12-13 20:15:29 +0000444
445 lsa = (struct router_lsa *) v->lsa;
446
447 p.family = AF_INET;
448 p.prefix = link->link_id;
449 p.prefixlen = ip_masklen (link->link_data);
450 apply_mask_ipv4 (&p);
451
452 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000453 zlog_debug ("ospf_intra_add_stub(): processing route to %s/%d",
paul718e3742002-12-13 20:15:29 +0000454 inet_ntoa (p.prefix), p.prefixlen);
455
456 /* (1) Calculate the distance D of stub network from the root. D is
457 equal to the distance from the root to the router vertex
458 (calculated in stage 1), plus the stub network link's advertised
459 cost. */
460 cost = v->distance + ntohs (link->m[0].metric);
461
462 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000463 zlog_debug ("ospf_intra_add_stub(): calculated cost is %d + %d = %d",
paul718e3742002-12-13 20:15:29 +0000464 v->distance, ntohs(link->m[0].metric), cost);
Paul Jakmab3bc68e2008-09-04 13:52:07 +0100465
466 /* PtP links with /32 masks adds host routes to remote, directly
467 * connected hosts, see RFC 2328, 12.4.1.1, Option 1.
468 * Such routes can just be ignored for the sake of tidyness.
469 */
470 if (parent_is_root && link->link_data.s_addr == 0xffffffff &&
471 ospf_if_lookup_by_local_addr (area->ospf, NULL, link->link_id))
472 {
473 if (IS_DEBUG_OSPF_EVENT)
474 zlog_debug ("%s: ignoring host route %s/32 to self.",
475 __func__, inet_ntoa (link->link_id));
476 return;
477 }
478
paul718e3742002-12-13 20:15:29 +0000479 rn = route_node_get (rt, (struct prefix *) &p);
480
481 /* Lookup current routing table. */
482 if (rn->info)
483 {
484 struct ospf_route *cur_or;
485
486 route_unlock_node (rn);
487
488 cur_or = rn->info;
489
490 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000491 zlog_debug ("ospf_intra_add_stub(): "
gdt630e4802004-08-31 17:28:41 +0000492 "another route to the same prefix found with cost %u",
493 cur_or->cost);
paul718e3742002-12-13 20:15:29 +0000494
495 /* Compare this distance to the current best cost to the stub
496 network. This is done by looking up the stub network's
497 current routing table entry. If the calculated distance D is
498 larger, go on to examine the next stub network link in the
499 LSA. */
500 if (cost > cur_or->cost)
501 {
502 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000503 zlog_debug ("ospf_intra_add_stub(): old route is better, exit");
paul718e3742002-12-13 20:15:29 +0000504 return;
505 }
506
507 /* (2) If this step is reached, the stub network's routing table
508 entry must be updated. Calculate the set of next hops that
509 would result from using the stub network link. This
510 calculation is shown in Section 16.1.1; input to this
511 calculation is the destination (the stub network) and the
512 parent vertex (the router vertex). If the distance D is the
513 same as the current routing table cost, simply add this set
514 of next hops to the routing table entry's list of next hops.
515 In this case, the routing table already has a Link State
516 Origin. If this Link State Origin is a router-LSA whose Link
517 State ID is smaller than V's Router ID, reset the Link State
518 Origin to V's router-LSA. */
519
520 if (cost == cur_or->cost)
521 {
522 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000523 zlog_debug ("ospf_intra_add_stub(): routes are equal, merge");
paul718e3742002-12-13 20:15:29 +0000524
525 ospf_route_copy_nexthops_from_vertex (cur_or, v);
526
527 if (IPV4_ADDR_CMP (&cur_or->u.std.origin->id, &lsa->header.id) < 0)
528 cur_or->u.std.origin = (struct lsa_header *) lsa;
529 return;
530 }
531
532 /* Otherwise D is smaller than the routing table cost.
533 Overwrite the current routing table entry by setting the
534 routing table entry's cost to D, and by setting the entry's
535 list of next hops to the newly calculated set. Set the
536 routing table entry's Link State Origin to V's router-LSA.
537 Then go on to examine the next stub network link. */
538
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(): new route is better, set it");
paul718e3742002-12-13 20:15:29 +0000543
544 cur_or->cost = cost;
545
paul048ba1d2003-08-15 16:04:21 +0000546 list_delete_all_node (cur_or->paths);
paul718e3742002-12-13 20:15:29 +0000547
548 ospf_route_copy_nexthops_from_vertex (cur_or, v);
549
550 cur_or->u.std.origin = (struct lsa_header *) lsa;
551 return;
552 }
553 }
554
555 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000556 zlog_debug ("ospf_intra_add_stub(): installing new route");
paul718e3742002-12-13 20:15:29 +0000557
558 or = ospf_route_new ();
559
560 or->id = v->id;
561 or->u.std.area_id = area->area_id;
paul718e3742002-12-13 20:15:29 +0000562 or->u.std.external_routing = area->external_routing;
paul718e3742002-12-13 20:15:29 +0000563 or->path_type = OSPF_PATH_INTRA_AREA;
564 or->cost = cost;
565 or->type = OSPF_DESTINATION_NETWORK;
566 or->u.std.origin = (struct lsa_header *) lsa;
paul718e3742002-12-13 20:15:29 +0000567
568 /* Nexthop is depend on connection type. */
569 if (v != area->spf)
570 {
571 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000572 zlog_debug ("ospf_intra_add_stub(): this network is on remote router");
paul718e3742002-12-13 20:15:29 +0000573 ospf_route_copy_nexthops_from_vertex (or, v);
574 }
575 else
576 {
577 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000578 zlog_debug ("ospf_intra_add_stub(): this network is on this router");
paul718e3742002-12-13 20:15:29 +0000579
paul6d1fab62003-06-22 08:28:18 +0000580 if ((oi = ospf_if_lookup_by_prefix (area->ospf, &p)))
paul718e3742002-12-13 20:15:29 +0000581 {
582 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000583 zlog_debug ("ospf_intra_add_stub(): the interface is %s",
paul718e3742002-12-13 20:15:29 +0000584 IF_NAME (oi));
585
586 path = ospf_path_new ();
587 path->nexthop.s_addr = 0;
Joakim Tjernlunda8ba8472009-07-27 12:42:34 +0200588 path->ifindex = oi->ifp->ifindex;
paul96735ee2003-08-10 02:51:22 +0000589 listnode_add (or->paths, path);
paul718e3742002-12-13 20:15:29 +0000590 }
591 else
592 {
593 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000594 zlog_debug ("ospf_intra_add_stub(): where's the interface ?");
paul718e3742002-12-13 20:15:29 +0000595 }
596 }
597
598 rn->info = or;
599
600 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000601 zlog_debug("ospf_intra_add_stub(): Stop");
paul718e3742002-12-13 20:15:29 +0000602}
603
hassoeb1ce602004-10-08 08:17:22 +0000604const char *ospf_path_type_str[] =
paul718e3742002-12-13 20:15:29 +0000605{
606 "unknown-type",
607 "intra-area",
608 "inter-area",
609 "type1-external",
610 "type2-external"
611};
612
613void
614ospf_route_table_dump (struct route_table *rt)
615{
616 struct route_node *rn;
617 struct ospf_route *or;
618 char buf1[BUFSIZ];
619 char buf2[BUFSIZ];
hasso52dc7ee2004-09-23 19:18:23 +0000620 struct listnode *pnode;
paul718e3742002-12-13 20:15:29 +0000621 struct ospf_path *path;
622
623#if 0
ajs2a42e282004-12-08 18:43:03 +0000624 zlog_debug ("Type Dest Area Path Type Cost Next Adv.");
625 zlog_debug (" Hop(s) Router(s)");
paul718e3742002-12-13 20:15:29 +0000626#endif /* 0 */
627
ajs2a42e282004-12-08 18:43:03 +0000628 zlog_debug ("========== OSPF routing table ==========");
paul718e3742002-12-13 20:15:29 +0000629 for (rn = route_top (rt); rn; rn = route_next (rn))
630 if ((or = rn->info) != NULL)
631 {
632 if (or->type == OSPF_DESTINATION_NETWORK)
633 {
ajs2a42e282004-12-08 18:43:03 +0000634 zlog_debug ("N %s/%d\t%s\t%s\t%d",
paul718e3742002-12-13 20:15:29 +0000635 inet_ntop (AF_INET, &rn->p.u.prefix4, buf1, BUFSIZ),
636 rn->p.prefixlen,
637 inet_ntop (AF_INET, &or->u.std.area_id, buf2,
638 BUFSIZ),
639 ospf_path_type_str[or->path_type],
640 or->cost);
paul1eb8ef22005-04-07 07:30:20 +0000641 for (ALL_LIST_ELEMENTS_RO (or->paths, pnode, path))
642 zlog_debug (" -> %s", inet_ntoa (path->nexthop));
paul718e3742002-12-13 20:15:29 +0000643 }
644 else
ajs2a42e282004-12-08 18:43:03 +0000645 zlog_debug ("R %s\t%s\t%s\t%d",
paul718e3742002-12-13 20:15:29 +0000646 inet_ntop (AF_INET, &rn->p.u.prefix4, buf1, BUFSIZ),
647 inet_ntop (AF_INET, &or->u.std.area_id, buf2,
648 BUFSIZ),
649 ospf_path_type_str[or->path_type],
650 or->cost);
651 }
ajs2a42e282004-12-08 18:43:03 +0000652 zlog_debug ("========================================");
paul718e3742002-12-13 20:15:29 +0000653}
654
paul718e3742002-12-13 20:15:29 +0000655/* This is 16.4.1 implementation.
656 o Intra-area paths using non-backbone areas are always the most preferred.
657 o The other paths, intra-area backbone paths and inter-area paths,
658 are of equal preference. */
paul4dadc292005-05-06 21:37:42 +0000659static int
paul6d1fab62003-06-22 08:28:18 +0000660ospf_asbr_route_cmp (struct ospf *ospf, struct ospf_route *r1,
661 struct ospf_route *r2)
paul718e3742002-12-13 20:15:29 +0000662{
663 u_char r1_type, r2_type;
664
665 r1_type = r1->path_type;
666 r2_type = r2->path_type;
667
paul718e3742002-12-13 20:15:29 +0000668 /* r1/r2 itself is backbone, and it's Inter-area path. */
669 if (OSPF_IS_AREA_ID_BACKBONE (r1->u.std.area_id))
670 r1_type = OSPF_PATH_INTER_AREA;
671 if (OSPF_IS_AREA_ID_BACKBONE (r2->u.std.area_id))
672 r2_type = OSPF_PATH_INTER_AREA;
673
674 return (r1_type - r2_type);
675}
676
677/* Compare two routes.
678 ret < 0 -- r1 is better.
679 ret == 0 -- r1 and r2 are the same.
680 ret > 0 -- r2 is better. */
681int
paul6d1fab62003-06-22 08:28:18 +0000682ospf_route_cmp (struct ospf *ospf, struct ospf_route *r1,
683 struct ospf_route *r2)
paul718e3742002-12-13 20:15:29 +0000684{
685 int ret = 0;
686
687 /* Path types of r1 and r2 are not the same. */
688 if ((ret = (r1->path_type - r2->path_type)))
689 return ret;
690
691 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000692 zlog_debug ("Route[Compare]: Path types are the same.");
paul718e3742002-12-13 20:15:29 +0000693 /* Path types are the same, compare any cost. */
694 switch (r1->path_type)
695 {
696 case OSPF_PATH_INTRA_AREA:
697 case OSPF_PATH_INTER_AREA:
698 break;
699 case OSPF_PATH_TYPE1_EXTERNAL:
paul6d1fab62003-06-22 08:28:18 +0000700 if (!CHECK_FLAG (ospf->config, OSPF_RFC1583_COMPATIBLE))
paul718e3742002-12-13 20:15:29 +0000701 {
paul6d1fab62003-06-22 08:28:18 +0000702 ret = ospf_asbr_route_cmp (ospf, r1->u.ext.asbr, r2->u.ext.asbr);
paul718e3742002-12-13 20:15:29 +0000703 if (ret != 0)
704 return ret;
705 }
706 break;
707 case OSPF_PATH_TYPE2_EXTERNAL:
708 if ((ret = (r1->u.ext.type2_cost - r2->u.ext.type2_cost)))
709 return ret;
710
paul6d1fab62003-06-22 08:28:18 +0000711 if (!CHECK_FLAG (ospf->config, OSPF_RFC1583_COMPATIBLE))
paul718e3742002-12-13 20:15:29 +0000712 {
paul6d1fab62003-06-22 08:28:18 +0000713 ret = ospf_asbr_route_cmp (ospf, r1->u.ext.asbr, r2->u.ext.asbr);
paul718e3742002-12-13 20:15:29 +0000714 if (ret != 0)
715 return ret;
716 }
717 break;
718 }
719
720 /* Anyway, compare the costs. */
721 return (r1->cost - r2->cost);
722}
723
paul4dadc292005-05-06 21:37:42 +0000724static int
paul718e3742002-12-13 20:15:29 +0000725ospf_path_exist (struct list *plist, struct in_addr nexthop,
726 struct ospf_interface *oi)
727{
paul1eb8ef22005-04-07 07:30:20 +0000728 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000729 struct ospf_path *path;
730
paul1eb8ef22005-04-07 07:30:20 +0000731 for (ALL_LIST_ELEMENTS (plist, node, nnode, path))
Joakim Tjernlunda8ba8472009-07-27 12:42:34 +0200732 if (IPV4_ADDR_SAME (&path->nexthop, &nexthop) &&
733 path->ifindex == oi->ifp->ifindex)
paul1eb8ef22005-04-07 07:30:20 +0000734 return 1;
paul718e3742002-12-13 20:15:29 +0000735
paul718e3742002-12-13 20:15:29 +0000736 return 0;
737}
738
739void
740ospf_route_copy_nexthops_from_vertex (struct ospf_route *to,
741 struct vertex *v)
742{
paul1eb8ef22005-04-07 07:30:20 +0000743 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000744 struct ospf_path *path;
745 struct vertex_nexthop *nexthop;
pauleb3da6d2005-10-18 04:20:33 +0000746 struct vertex_parent *vp;
paul718e3742002-12-13 20:15:29 +0000747
paul96735ee2003-08-10 02:51:22 +0000748 assert (to->paths);
paul718e3742002-12-13 20:15:29 +0000749
pauleb3da6d2005-10-18 04:20:33 +0000750 for (ALL_LIST_ELEMENTS_RO (v->parents, node, vp))
paul718e3742002-12-13 20:15:29 +0000751 {
pauleb3da6d2005-10-18 04:20:33 +0000752 nexthop = vp->nexthop;
753
paul718e3742002-12-13 20:15:29 +0000754 if (nexthop->oi != NULL)
755 {
paul96735ee2003-08-10 02:51:22 +0000756 if (! ospf_path_exist (to->paths, nexthop->router, nexthop->oi))
paul718e3742002-12-13 20:15:29 +0000757 {
758 path = ospf_path_new ();
759 path->nexthop = nexthop->router;
Joakim Tjernlunda8ba8472009-07-27 12:42:34 +0200760 path->ifindex = nexthop->oi->ifp->ifindex;
paul96735ee2003-08-10 02:51:22 +0000761 listnode_add (to->paths, path);
paul718e3742002-12-13 20:15:29 +0000762 }
763 }
764 }
765}
766
767struct ospf_path *
hasso52dc7ee2004-09-23 19:18:23 +0000768ospf_path_lookup (struct list *plist, struct ospf_path *path)
paul718e3742002-12-13 20:15:29 +0000769{
hasso52dc7ee2004-09-23 19:18:23 +0000770 struct listnode *node;
paul1eb8ef22005-04-07 07:30:20 +0000771 struct ospf_path *op;
paul718e3742002-12-13 20:15:29 +0000772
paul1eb8ef22005-04-07 07:30:20 +0000773 for (ALL_LIST_ELEMENTS_RO (plist, node, op))
Joakim Tjernlund77a1c4e2009-02-01 11:12:11 +0100774 {
775 if (!IPV4_ADDR_SAME (&op->nexthop, &path->nexthop))
776 continue;
777 if (!IPV4_ADDR_SAME (&op->adv_router, &path->adv_router))
778 continue;
Joakim Tjernlunda8ba8472009-07-27 12:42:34 +0200779 if (op->ifindex != path->ifindex)
Joakim Tjernlund77a1c4e2009-02-01 11:12:11 +0100780 continue;
781 return op;
782 }
paul718e3742002-12-13 20:15:29 +0000783 return NULL;
784}
785
786void
hasso52dc7ee2004-09-23 19:18:23 +0000787ospf_route_copy_nexthops (struct ospf_route *to, struct list *from)
paul718e3742002-12-13 20:15:29 +0000788{
paul1eb8ef22005-04-07 07:30:20 +0000789 struct listnode *node, *nnode;
790 struct ospf_path *path;
paul718e3742002-12-13 20:15:29 +0000791
paul96735ee2003-08-10 02:51:22 +0000792 assert (to->paths);
paul718e3742002-12-13 20:15:29 +0000793
paul1eb8ef22005-04-07 07:30:20 +0000794 for (ALL_LIST_ELEMENTS (from, node, nnode, path))
paul718e3742002-12-13 20:15:29 +0000795 /* The same routes are just discarded. */
paul1eb8ef22005-04-07 07:30:20 +0000796 if (!ospf_path_lookup (to->paths, path))
797 listnode_add (to->paths, ospf_path_dup (path));
paul718e3742002-12-13 20:15:29 +0000798}
799
800void
hasso52dc7ee2004-09-23 19:18:23 +0000801ospf_route_subst_nexthops (struct ospf_route *to, struct list *from)
paul718e3742002-12-13 20:15:29 +0000802{
paul718e3742002-12-13 20:15:29 +0000803
paul96735ee2003-08-10 02:51:22 +0000804 list_delete_all_node (to->paths);
paul718e3742002-12-13 20:15:29 +0000805 ospf_route_copy_nexthops (to, from);
806}
807
808void
809ospf_route_subst (struct route_node *rn, struct ospf_route *new_or,
810 struct ospf_route *over)
811{
812 route_lock_node (rn);
813 ospf_route_free (rn->info);
814
paul96735ee2003-08-10 02:51:22 +0000815 ospf_route_copy_nexthops (new_or, over->paths);
paul718e3742002-12-13 20:15:29 +0000816 rn->info = new_or;
817 route_unlock_node (rn);
818}
819
820void
821ospf_route_add (struct route_table *rt, struct prefix_ipv4 *p,
822 struct ospf_route *new_or, struct ospf_route *over)
823{
824 struct route_node *rn;
825
826 rn = route_node_get (rt, (struct prefix *) p);
827
paul96735ee2003-08-10 02:51:22 +0000828 ospf_route_copy_nexthops (new_or, over->paths);
paul718e3742002-12-13 20:15:29 +0000829
830 if (rn->info)
831 {
832 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000833 zlog_debug ("ospf_route_add(): something's wrong !");
paul718e3742002-12-13 20:15:29 +0000834 route_unlock_node (rn);
835 return;
836 }
837
838 rn->info = new_or;
839}
840
841void
842ospf_prune_unreachable_networks (struct route_table *rt)
843{
844 struct route_node *rn, *next;
845 struct ospf_route *or;
846
847 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000848 zlog_debug ("Pruning unreachable networks");
paul718e3742002-12-13 20:15:29 +0000849
850 for (rn = route_top (rt); rn; rn = next)
851 {
852 next = route_next (rn);
853 if (rn->info != NULL)
854 {
855 or = rn->info;
paul96735ee2003-08-10 02:51:22 +0000856 if (listcount (or->paths) == 0)
paul718e3742002-12-13 20:15:29 +0000857 {
858 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000859 zlog_debug ("Pruning route to %s/%d",
paul718e3742002-12-13 20:15:29 +0000860 inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen);
861
862 ospf_route_free (or);
863 rn->info = NULL;
864 route_unlock_node (rn);
865 }
866 }
867 }
868}
869
870void
871ospf_prune_unreachable_routers (struct route_table *rtrs)
872{
873 struct route_node *rn, *next;
874 struct ospf_route *or;
paul1eb8ef22005-04-07 07:30:20 +0000875 struct listnode *node, *nnode;
hasso52dc7ee2004-09-23 19:18:23 +0000876 struct list *paths;
paul718e3742002-12-13 20:15:29 +0000877
878 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000879 zlog_debug ("Pruning unreachable routers");
paul718e3742002-12-13 20:15:29 +0000880
881 for (rn = route_top (rtrs); rn; rn = next)
882 {
883 next = route_next (rn);
884 if ((paths = rn->info) == NULL)
885 continue;
886
paul1eb8ef22005-04-07 07:30:20 +0000887 for (ALL_LIST_ELEMENTS (paths, node, nnode, or))
paul718e3742002-12-13 20:15:29 +0000888 {
paul96735ee2003-08-10 02:51:22 +0000889 if (listcount (or->paths) == 0)
paul718e3742002-12-13 20:15:29 +0000890 {
891 if (IS_DEBUG_OSPF_EVENT)
892 {
ajs2a42e282004-12-08 18:43:03 +0000893 zlog_debug ("Pruning route to rtr %s",
paul718e3742002-12-13 20:15:29 +0000894 inet_ntoa (rn->p.u.prefix4));
ajs2a42e282004-12-08 18:43:03 +0000895 zlog_debug (" via area %s",
paul718e3742002-12-13 20:15:29 +0000896 inet_ntoa (or->u.std.area_id));
897 }
898
899 listnode_delete (paths, or);
900 ospf_route_free (or);
901 }
902 }
903
904 if (listcount (paths) == 0)
905 {
906 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000907 zlog_debug ("Pruning router node %s", inet_ntoa (rn->p.u.prefix4));
paul718e3742002-12-13 20:15:29 +0000908
909 list_delete (paths);
910 rn->info = NULL;
911 route_unlock_node (rn);
912 }
913 }
914}
915
916int
917ospf_add_discard_route (struct route_table *rt, struct ospf_area *area,
918 struct prefix_ipv4 *p)
919{
920 struct route_node *rn;
921 struct ospf_route *or, *new_or;
922
923 rn = route_node_get (rt, (struct prefix *) p);
924
925 if (rn == NULL)
926 {
927 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000928 zlog_debug ("ospf_add_discard_route(): router installation error");
paul718e3742002-12-13 20:15:29 +0000929 return 0;
930 }
931
932 if (rn->info) /* If the route to the same destination is found */
933 {
934 route_unlock_node (rn);
935
936 or = rn->info;
937
938 if (or->path_type == OSPF_PATH_INTRA_AREA)
939 {
940 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000941 zlog_debug ("ospf_add_discard_route(): "
paul718e3742002-12-13 20:15:29 +0000942 "an intra-area route exists");
943 return 0;
944 }
945
946 if (or->type == OSPF_DESTINATION_DISCARD)
947 {
948 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000949 zlog_debug ("ospf_add_discard_route(): "
paul718e3742002-12-13 20:15:29 +0000950 "discard entry already installed");
951 return 0;
952 }
953
954 ospf_route_free (rn->info);
955 }
956
957 new_or = ospf_route_new ();
958 new_or->type = OSPF_DESTINATION_DISCARD;
959 new_or->id.s_addr = 0;
960 new_or->cost = 0;
961 new_or->u.std.area_id = area->area_id;
paul718e3742002-12-13 20:15:29 +0000962 new_or->u.std.external_routing = area->external_routing;
paul718e3742002-12-13 20:15:29 +0000963 new_or->path_type = OSPF_PATH_INTER_AREA;
964 rn->info = new_or;
965
966 ospf_zebra_add_discard (p);
967
968 return 1;
969}
970
971void
972ospf_delete_discard_route (struct prefix_ipv4 *p)
973{
974 ospf_zebra_delete_discard(p);
975}
976