blob: eb7829acdf1bd160914d219974f0e2719c82f76e [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
Ayan Banerjee16a86b32012-12-03 10:48:46 -0800129/* If a prefix exists in the new routing table, then return 1,
130 otherwise return 0. Since the ZEBRA-RIB does an implicit
131 withdraw, it is not necessary to send a delete, an add later
132 will act like an implicit delete. */
133static int
134ospf_route_exist_new_table (struct route_table *rt, struct prefix_ipv4 *prefix)
135{
136 struct route_node *rn;
137
138 assert (rt);
139 assert (prefix);
140
141 rn = route_node_lookup (rt, (struct prefix *) prefix);
142 if (!rn) {
143 return 0;
144 }
145 route_unlock_node (rn);
146
147 if (!rn->info) {
148 return 0;
149 }
150
151 return 1;
152}
153
paul718e3742002-12-13 20:15:29 +0000154/* If a prefix and a nexthop match any route in the routing table,
155 then return 1, otherwise return 0. */
156int
157ospf_route_match_same (struct route_table *rt, struct prefix_ipv4 *prefix,
158 struct ospf_route *newor)
159{
160 struct route_node *rn;
161 struct ospf_route *or;
162 struct ospf_path *op;
163 struct ospf_path *newop;
hasso52dc7ee2004-09-23 19:18:23 +0000164 struct listnode *n1;
165 struct listnode *n2;
paul718e3742002-12-13 20:15:29 +0000166
167 if (! rt || ! prefix)
168 return 0;
169
170 rn = route_node_lookup (rt, (struct prefix *) prefix);
171 if (! rn || ! rn->info)
172 return 0;
173
174 route_unlock_node (rn);
175
176 or = rn->info;
177 if (or->type == newor->type && or->cost == newor->cost)
178 {
179 if (or->type == OSPF_DESTINATION_NETWORK)
180 {
paul96735ee2003-08-10 02:51:22 +0000181 if (or->paths->count != newor->paths->count)
paul718e3742002-12-13 20:15:29 +0000182 return 0;
183
184 /* Check each path. */
paul96735ee2003-08-10 02:51:22 +0000185 for (n1 = listhead (or->paths), n2 = listhead (newor->paths);
paul1eb8ef22005-04-07 07:30:20 +0000186 n1 && n2; n1 = listnextnode (n1), n2 = listnextnode (n2))
paul718e3742002-12-13 20:15:29 +0000187 {
paul1eb8ef22005-04-07 07:30:20 +0000188 op = listgetdata (n1);
189 newop = listgetdata (n2);
paul718e3742002-12-13 20:15:29 +0000190
191 if (! IPV4_ADDR_SAME (&op->nexthop, &newop->nexthop))
192 return 0;
Joakim Tjernlunda8ba8472009-07-27 12:42:34 +0200193 if (op->ifindex != newop->ifindex)
Joakim Tjernlund77a1c4e2009-02-01 11:12:11 +0100194 return 0;
paul718e3742002-12-13 20:15:29 +0000195 }
196 return 1;
197 }
198 else if (prefix_same (&rn->p, (struct prefix *) prefix))
199 return 1;
200 }
201 return 0;
202}
203
paul6d1fab62003-06-22 08:28:18 +0000204/* delete routes generated from AS-External routes if there is a inter/intra
205 * area route
206 */
paul4dadc292005-05-06 21:37:42 +0000207static void
paul6d1fab62003-06-22 08:28:18 +0000208ospf_route_delete_same_ext(struct route_table *external_routes,
209 struct route_table *routes)
210{
211 struct route_node *rn,
212 *ext_rn;
213
214 if ( (external_routes == NULL) || (routes == NULL) )
215 return;
216
217 /* Remove deleted routes */
218 for ( rn = route_top (routes); rn; rn = route_next (rn) )
219 {
220 if (rn && rn->info)
221 {
hassofa2b17e2004-03-04 17:45:00 +0000222 struct prefix_ipv4 *p = (struct prefix_ipv4 *)(&rn->p);
223 if ( (ext_rn = route_node_lookup (external_routes, (struct prefix *)p)) )
paul6d1fab62003-06-22 08:28:18 +0000224 {
paul6d1fab62003-06-22 08:28:18 +0000225 if (ext_rn->info)
226 {
Paul Jakma894f8b62006-05-12 22:50:40 +0000227 ospf_zebra_delete (p, ext_rn->info);
paul6d1fab62003-06-22 08:28:18 +0000228 ospf_route_free( ext_rn->info);
229 ext_rn->info = NULL;
230 }
231 route_unlock_node (ext_rn);
232 }
233 }
234 }
235}
236
paul718e3742002-12-13 20:15:29 +0000237/* rt: Old, cmprt: New */
paul4dadc292005-05-06 21:37:42 +0000238static void
paul718e3742002-12-13 20:15:29 +0000239ospf_route_delete_uniq (struct route_table *rt, struct route_table *cmprt)
240{
241 struct route_node *rn;
242 struct ospf_route *or;
243
244 for (rn = route_top (rt); rn; rn = route_next (rn))
245 if ((or = rn->info) != NULL)
246 if (or->path_type == OSPF_PATH_INTRA_AREA ||
247 or->path_type == OSPF_PATH_INTER_AREA)
248 {
249 if (or->type == OSPF_DESTINATION_NETWORK)
250 {
Ayan Banerjee16a86b32012-12-03 10:48:46 -0800251 if (! ospf_route_exist_new_table (cmprt,
252 (struct prefix_ipv4 *) &rn->p))
paul718e3742002-12-13 20:15:29 +0000253 ospf_zebra_delete ((struct prefix_ipv4 *) &rn->p, or);
254 }
255 else if (or->type == OSPF_DESTINATION_DISCARD)
Ayan Banerjee16a86b32012-12-03 10:48:46 -0800256 if (! ospf_route_exist_new_table (cmprt,
257 (struct prefix_ipv4 *) &rn->p))
paul718e3742002-12-13 20:15:29 +0000258 ospf_zebra_delete_discard ((struct prefix_ipv4 *) &rn->p);
259 }
260}
261
262/* Install routes to table. */
263void
paul6d1fab62003-06-22 08:28:18 +0000264ospf_route_install (struct ospf *ospf, struct route_table *rt)
paul718e3742002-12-13 20:15:29 +0000265{
266 struct route_node *rn;
267 struct ospf_route *or;
268
269 /* rt contains new routing table, new_table contains an old one.
270 updating pointers */
paul6d1fab62003-06-22 08:28:18 +0000271 if (ospf->old_table)
272 ospf_route_table_free (ospf->old_table);
273
274 ospf->old_table = ospf->new_table;
275 ospf->new_table = rt;
paul718e3742002-12-13 20:15:29 +0000276
277 /* Delete old routes. */
paul6d1fab62003-06-22 08:28:18 +0000278 if (ospf->old_table)
279 ospf_route_delete_uniq (ospf->old_table, rt);
280 if (ospf->old_external_route)
281 ospf_route_delete_same_ext (ospf->old_external_route, rt);
paul718e3742002-12-13 20:15:29 +0000282
283 /* Install new routes. */
284 for (rn = route_top (rt); rn; rn = route_next (rn))
285 if ((or = rn->info) != NULL)
286 {
287 if (or->type == OSPF_DESTINATION_NETWORK)
288 {
paul6d1fab62003-06-22 08:28:18 +0000289 if (! ospf_route_match_same (ospf->old_table,
paul718e3742002-12-13 20:15:29 +0000290 (struct prefix_ipv4 *)&rn->p, or))
291 ospf_zebra_add ((struct prefix_ipv4 *) &rn->p, or);
292 }
293 else if (or->type == OSPF_DESTINATION_DISCARD)
paul6d1fab62003-06-22 08:28:18 +0000294 if (! ospf_route_match_same (ospf->old_table,
paul718e3742002-12-13 20:15:29 +0000295 (struct prefix_ipv4 *) &rn->p, or))
296 ospf_zebra_add_discard ((struct prefix_ipv4 *) &rn->p);
297 }
298}
299
paul718e3742002-12-13 20:15:29 +0000300/* RFC2328 16.1. (4). For "router". */
301void
302ospf_intra_add_router (struct route_table *rt, struct vertex *v,
303 struct ospf_area *area)
304{
305 struct route_node *rn;
306 struct ospf_route *or;
307 struct prefix_ipv4 p;
308 struct router_lsa *lsa;
309
310 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000311 zlog_debug ("ospf_intra_add_router: Start");
paul718e3742002-12-13 20:15:29 +0000312
313 lsa = (struct router_lsa *) v->lsa;
314
315 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000316 zlog_debug ("ospf_intra_add_router: LS ID: %s",
paul718e3742002-12-13 20:15:29 +0000317 inet_ntoa (lsa->header.id));
Paul Jakma9c27ef92006-05-04 07:32:57 +0000318
319 if (!OSPF_IS_AREA_BACKBONE(area))
320 ospf_vl_up_check (area, lsa->header.id, v);
paul718e3742002-12-13 20:15:29 +0000321
322 if (!CHECK_FLAG (lsa->flags, ROUTER_LSA_SHORTCUT))
323 area->shortcut_capability = 0;
324
325 /* If the newly added vertex is an area border router or AS boundary
326 router, a routing table entry is added whose destination type is
327 "router". */
328 if (! IS_ROUTER_LSA_BORDER (lsa) && ! IS_ROUTER_LSA_EXTERNAL (lsa))
329 {
330 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000331 zlog_debug ("ospf_intra_add_router: "
paul718e3742002-12-13 20:15:29 +0000332 "this router is neither ASBR nor ABR, skipping it");
333 return;
334 }
335
336 /* Update ABR and ASBR count in this area. */
337 if (IS_ROUTER_LSA_BORDER (lsa))
338 area->abr_count++;
339 if (IS_ROUTER_LSA_EXTERNAL (lsa))
340 area->asbr_count++;
341
342 /* The Options field found in the associated router-LSA is copied
343 into the routing table entry's Optional capabilities field. Call
344 the newly added vertex Router X. */
345 or = ospf_route_new ();
346
347 or->id = v->id;
348 or->u.std.area_id = area->area_id;
paul718e3742002-12-13 20:15:29 +0000349 or->u.std.external_routing = area->external_routing;
paul718e3742002-12-13 20:15:29 +0000350 or->path_type = OSPF_PATH_INTRA_AREA;
351 or->cost = v->distance;
352 or->type = OSPF_DESTINATION_ROUTER;
353 or->u.std.origin = (struct lsa_header *) lsa;
354 or->u.std.options = lsa->header.options;
355 or->u.std.flags = lsa->flags;
356
357 /* If Router X is the endpoint of one of the calculating router's
358 virtual links, and the virtual link uses Area A as Transit area:
359 the virtual link is declared up, the IP address of the virtual
360 interface is set to the IP address of the outgoing interface
361 calculated above for Router X, and the virtual neighbor's IP
362 address is set to Router X's interface address (contained in
363 Router X's router-LSA) that points back to the root of the
364 shortest- path tree; equivalently, this is the interface that
365 points back to Router X's parent vertex on the shortest-path tree
366 (similar to the calculation in Section 16.1.1). */
367
368 p.family = AF_INET;
369 p.prefix = v->id;
370 p.prefixlen = IPV4_MAX_BITLEN;
371
372 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000373 zlog_debug ("ospf_intra_add_router: talking about %s/%d",
paul718e3742002-12-13 20:15:29 +0000374 inet_ntoa (p.prefix), p.prefixlen);
375
376 rn = route_node_get (rt, (struct prefix *) &p);
377
378 /* Note that we keep all routes to ABRs and ASBRs, not only the best */
379 if (rn->info == NULL)
380 rn->info = list_new ();
381 else
382 route_unlock_node (rn);
383
384 ospf_route_copy_nexthops_from_vertex (or, v);
385
386 listnode_add (rn->info, or);
387
hasso9e1be242004-04-20 03:50:59 +0000388 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000389 zlog_debug ("ospf_intra_add_router: Stop");
paul718e3742002-12-13 20:15:29 +0000390}
391
392/* RFC2328 16.1. (4). For transit network. */
393void
394ospf_intra_add_transit (struct route_table *rt, struct vertex *v,
395 struct ospf_area *area)
396{
397 struct route_node *rn;
398 struct ospf_route *or;
399 struct prefix_ipv4 p;
400 struct network_lsa *lsa;
401
402 lsa = (struct network_lsa*) v->lsa;
403
404 /* If the newly added vertex is a transit network, the routing table
405 entry for the network is located. The entry's Destination ID is
406 the IP network number, which can be obtained by masking the
407 Vertex ID (Link State ID) with its associated subnet mask (found
408 in the body of the associated network-LSA). */
409 p.family = AF_INET;
410 p.prefix = v->id;
411 p.prefixlen = ip_masklen (lsa->mask);
412 apply_mask_ipv4 (&p);
413
414 rn = route_node_get (rt, (struct prefix *) &p);
415
416 /* If the routing table entry already exists (i.e., there is already
417 an intra-area route to the destination installed in the routing
418 table), multiple vertices have mapped to the same IP network.
419 For example, this can occur when a new Designated Router is being
420 established. In this case, the current routing table entry
421 should be overwritten if and only if the newly found path is just
422 as short and the current routing table entry's Link State Origin
423 has a smaller Link State ID than the newly added vertex' LSA. */
424 if (rn->info)
425 {
426 struct ospf_route *cur_or;
427
428 route_unlock_node (rn);
429 cur_or = rn->info;
430
431 if (v->distance > cur_or->cost ||
432 IPV4_ADDR_CMP (&cur_or->u.std.origin->id, &lsa->header.id) > 0)
433 return;
434
435 ospf_route_free (rn->info);
436 }
437
438 or = ospf_route_new ();
439
440 or->id = v->id;
441 or->u.std.area_id = area->area_id;
paul718e3742002-12-13 20:15:29 +0000442 or->u.std.external_routing = area->external_routing;
paul718e3742002-12-13 20:15:29 +0000443 or->path_type = OSPF_PATH_INTRA_AREA;
444 or->cost = v->distance;
445 or->type = OSPF_DESTINATION_NETWORK;
446 or->u.std.origin = (struct lsa_header *) lsa;
447
448 ospf_route_copy_nexthops_from_vertex (or, v);
449
450 rn->info = or;
451}
452
453/* RFC2328 16.1. second stage. */
454void
455ospf_intra_add_stub (struct route_table *rt, struct router_lsa_link *link,
Paul Jakmab3bc68e2008-09-04 13:52:07 +0100456 struct vertex *v, struct ospf_area *area,
Joakim Tjernlund57c639f2012-07-07 17:06:12 +0200457 int parent_is_root, int lsa_pos)
paul718e3742002-12-13 20:15:29 +0000458{
459 u_int32_t cost;
460 struct route_node *rn;
461 struct ospf_route *or;
462 struct prefix_ipv4 p;
463 struct router_lsa *lsa;
464 struct ospf_interface *oi;
465 struct ospf_path *path;
466
467 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000468 zlog_debug ("ospf_intra_add_stub(): Start");
paul718e3742002-12-13 20:15:29 +0000469
470 lsa = (struct router_lsa *) v->lsa;
471
472 p.family = AF_INET;
473 p.prefix = link->link_id;
474 p.prefixlen = ip_masklen (link->link_data);
475 apply_mask_ipv4 (&p);
476
477 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000478 zlog_debug ("ospf_intra_add_stub(): processing route to %s/%d",
paul718e3742002-12-13 20:15:29 +0000479 inet_ntoa (p.prefix), p.prefixlen);
480
481 /* (1) Calculate the distance D of stub network from the root. D is
482 equal to the distance from the root to the router vertex
483 (calculated in stage 1), plus the stub network link's advertised
484 cost. */
485 cost = v->distance + ntohs (link->m[0].metric);
486
487 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000488 zlog_debug ("ospf_intra_add_stub(): calculated cost is %d + %d = %d",
paul718e3742002-12-13 20:15:29 +0000489 v->distance, ntohs(link->m[0].metric), cost);
Paul Jakmab3bc68e2008-09-04 13:52:07 +0100490
491 /* PtP links with /32 masks adds host routes to remote, directly
492 * connected hosts, see RFC 2328, 12.4.1.1, Option 1.
493 * Such routes can just be ignored for the sake of tidyness.
494 */
495 if (parent_is_root && link->link_data.s_addr == 0xffffffff &&
496 ospf_if_lookup_by_local_addr (area->ospf, NULL, link->link_id))
497 {
498 if (IS_DEBUG_OSPF_EVENT)
499 zlog_debug ("%s: ignoring host route %s/32 to self.",
500 __func__, inet_ntoa (link->link_id));
501 return;
502 }
503
paul718e3742002-12-13 20:15:29 +0000504 rn = route_node_get (rt, (struct prefix *) &p);
505
506 /* Lookup current routing table. */
507 if (rn->info)
508 {
509 struct ospf_route *cur_or;
510
511 route_unlock_node (rn);
512
513 cur_or = rn->info;
514
515 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000516 zlog_debug ("ospf_intra_add_stub(): "
gdt630e4802004-08-31 17:28:41 +0000517 "another route to the same prefix found with cost %u",
518 cur_or->cost);
paul718e3742002-12-13 20:15:29 +0000519
520 /* Compare this distance to the current best cost to the stub
521 network. This is done by looking up the stub network's
522 current routing table entry. If the calculated distance D is
523 larger, go on to examine the next stub network link in the
524 LSA. */
525 if (cost > cur_or->cost)
526 {
527 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000528 zlog_debug ("ospf_intra_add_stub(): old route is better, exit");
paul718e3742002-12-13 20:15:29 +0000529 return;
530 }
531
532 /* (2) If this step is reached, the stub network's routing table
533 entry must be updated. Calculate the set of next hops that
534 would result from using the stub network link. This
535 calculation is shown in Section 16.1.1; input to this
536 calculation is the destination (the stub network) and the
537 parent vertex (the router vertex). If the distance D is the
538 same as the current routing table cost, simply add this set
539 of next hops to the routing table entry's list of next hops.
540 In this case, the routing table already has a Link State
541 Origin. If this Link State Origin is a router-LSA whose Link
542 State ID is smaller than V's Router ID, reset the Link State
543 Origin to V's router-LSA. */
544
545 if (cost == cur_or->cost)
546 {
547 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000548 zlog_debug ("ospf_intra_add_stub(): routes are equal, merge");
paul718e3742002-12-13 20:15:29 +0000549
550 ospf_route_copy_nexthops_from_vertex (cur_or, v);
551
552 if (IPV4_ADDR_CMP (&cur_or->u.std.origin->id, &lsa->header.id) < 0)
553 cur_or->u.std.origin = (struct lsa_header *) lsa;
554 return;
555 }
556
557 /* Otherwise D is smaller than the routing table cost.
558 Overwrite the current routing table entry by setting the
559 routing table entry's cost to D, and by setting the entry's
560 list of next hops to the newly calculated set. Set the
561 routing table entry's Link State Origin to V's router-LSA.
562 Then go on to examine the next stub network link. */
563
564 if (cost < cur_or->cost)
565 {
566 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000567 zlog_debug ("ospf_intra_add_stub(): new route is better, set it");
paul718e3742002-12-13 20:15:29 +0000568
569 cur_or->cost = cost;
570
paul048ba1d2003-08-15 16:04:21 +0000571 list_delete_all_node (cur_or->paths);
paul718e3742002-12-13 20:15:29 +0000572
573 ospf_route_copy_nexthops_from_vertex (cur_or, v);
574
575 cur_or->u.std.origin = (struct lsa_header *) lsa;
576 return;
577 }
578 }
579
580 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000581 zlog_debug ("ospf_intra_add_stub(): installing new route");
paul718e3742002-12-13 20:15:29 +0000582
583 or = ospf_route_new ();
584
585 or->id = v->id;
586 or->u.std.area_id = area->area_id;
paul718e3742002-12-13 20:15:29 +0000587 or->u.std.external_routing = area->external_routing;
paul718e3742002-12-13 20:15:29 +0000588 or->path_type = OSPF_PATH_INTRA_AREA;
589 or->cost = cost;
590 or->type = OSPF_DESTINATION_NETWORK;
591 or->u.std.origin = (struct lsa_header *) lsa;
paul718e3742002-12-13 20:15:29 +0000592
593 /* Nexthop is depend on connection type. */
594 if (v != area->spf)
595 {
596 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000597 zlog_debug ("ospf_intra_add_stub(): this network is on remote router");
paul718e3742002-12-13 20:15:29 +0000598 ospf_route_copy_nexthops_from_vertex (or, v);
599 }
600 else
601 {
602 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000603 zlog_debug ("ospf_intra_add_stub(): this network is on this router");
paul718e3742002-12-13 20:15:29 +0000604
Joakim Tjernlund57c639f2012-07-07 17:06:12 +0200605 if ((oi = ospf_if_lookup_by_lsa_pos (area, lsa_pos)))
paul718e3742002-12-13 20:15:29 +0000606 {
607 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000608 zlog_debug ("ospf_intra_add_stub(): the interface is %s",
paul718e3742002-12-13 20:15:29 +0000609 IF_NAME (oi));
610
611 path = ospf_path_new ();
612 path->nexthop.s_addr = 0;
Joakim Tjernlunda8ba8472009-07-27 12:42:34 +0200613 path->ifindex = oi->ifp->ifindex;
paul96735ee2003-08-10 02:51:22 +0000614 listnode_add (or->paths, path);
paul718e3742002-12-13 20:15:29 +0000615 }
616 else
617 {
618 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000619 zlog_debug ("ospf_intra_add_stub(): where's the interface ?");
paul718e3742002-12-13 20:15:29 +0000620 }
621 }
622
623 rn->info = or;
624
625 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000626 zlog_debug("ospf_intra_add_stub(): Stop");
paul718e3742002-12-13 20:15:29 +0000627}
628
hassoeb1ce602004-10-08 08:17:22 +0000629const char *ospf_path_type_str[] =
paul718e3742002-12-13 20:15:29 +0000630{
631 "unknown-type",
632 "intra-area",
633 "inter-area",
634 "type1-external",
635 "type2-external"
636};
637
638void
639ospf_route_table_dump (struct route_table *rt)
640{
641 struct route_node *rn;
642 struct ospf_route *or;
643 char buf1[BUFSIZ];
644 char buf2[BUFSIZ];
hasso52dc7ee2004-09-23 19:18:23 +0000645 struct listnode *pnode;
paul718e3742002-12-13 20:15:29 +0000646 struct ospf_path *path;
647
648#if 0
ajs2a42e282004-12-08 18:43:03 +0000649 zlog_debug ("Type Dest Area Path Type Cost Next Adv.");
650 zlog_debug (" Hop(s) Router(s)");
paul718e3742002-12-13 20:15:29 +0000651#endif /* 0 */
652
ajs2a42e282004-12-08 18:43:03 +0000653 zlog_debug ("========== OSPF routing table ==========");
paul718e3742002-12-13 20:15:29 +0000654 for (rn = route_top (rt); rn; rn = route_next (rn))
655 if ((or = rn->info) != NULL)
656 {
657 if (or->type == OSPF_DESTINATION_NETWORK)
658 {
ajs2a42e282004-12-08 18:43:03 +0000659 zlog_debug ("N %s/%d\t%s\t%s\t%d",
paul718e3742002-12-13 20:15:29 +0000660 inet_ntop (AF_INET, &rn->p.u.prefix4, buf1, BUFSIZ),
661 rn->p.prefixlen,
662 inet_ntop (AF_INET, &or->u.std.area_id, buf2,
663 BUFSIZ),
664 ospf_path_type_str[or->path_type],
665 or->cost);
paul1eb8ef22005-04-07 07:30:20 +0000666 for (ALL_LIST_ELEMENTS_RO (or->paths, pnode, path))
667 zlog_debug (" -> %s", inet_ntoa (path->nexthop));
paul718e3742002-12-13 20:15:29 +0000668 }
669 else
ajs2a42e282004-12-08 18:43:03 +0000670 zlog_debug ("R %s\t%s\t%s\t%d",
paul718e3742002-12-13 20:15:29 +0000671 inet_ntop (AF_INET, &rn->p.u.prefix4, buf1, BUFSIZ),
672 inet_ntop (AF_INET, &or->u.std.area_id, buf2,
673 BUFSIZ),
674 ospf_path_type_str[or->path_type],
675 or->cost);
676 }
ajs2a42e282004-12-08 18:43:03 +0000677 zlog_debug ("========================================");
paul718e3742002-12-13 20:15:29 +0000678}
679
paul718e3742002-12-13 20:15:29 +0000680/* This is 16.4.1 implementation.
681 o Intra-area paths using non-backbone areas are always the most preferred.
682 o The other paths, intra-area backbone paths and inter-area paths,
683 are of equal preference. */
paul4dadc292005-05-06 21:37:42 +0000684static int
paul6d1fab62003-06-22 08:28:18 +0000685ospf_asbr_route_cmp (struct ospf *ospf, struct ospf_route *r1,
686 struct ospf_route *r2)
paul718e3742002-12-13 20:15:29 +0000687{
688 u_char r1_type, r2_type;
689
690 r1_type = r1->path_type;
691 r2_type = r2->path_type;
692
paul718e3742002-12-13 20:15:29 +0000693 /* r1/r2 itself is backbone, and it's Inter-area path. */
694 if (OSPF_IS_AREA_ID_BACKBONE (r1->u.std.area_id))
695 r1_type = OSPF_PATH_INTER_AREA;
696 if (OSPF_IS_AREA_ID_BACKBONE (r2->u.std.area_id))
697 r2_type = OSPF_PATH_INTER_AREA;
698
699 return (r1_type - r2_type);
700}
701
702/* Compare two routes.
703 ret < 0 -- r1 is better.
704 ret == 0 -- r1 and r2 are the same.
705 ret > 0 -- r2 is better. */
706int
paul6d1fab62003-06-22 08:28:18 +0000707ospf_route_cmp (struct ospf *ospf, struct ospf_route *r1,
708 struct ospf_route *r2)
paul718e3742002-12-13 20:15:29 +0000709{
710 int ret = 0;
711
712 /* Path types of r1 and r2 are not the same. */
713 if ((ret = (r1->path_type - r2->path_type)))
714 return ret;
715
716 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000717 zlog_debug ("Route[Compare]: Path types are the same.");
paul718e3742002-12-13 20:15:29 +0000718 /* Path types are the same, compare any cost. */
719 switch (r1->path_type)
720 {
721 case OSPF_PATH_INTRA_AREA:
722 case OSPF_PATH_INTER_AREA:
723 break;
724 case OSPF_PATH_TYPE1_EXTERNAL:
paul6d1fab62003-06-22 08:28:18 +0000725 if (!CHECK_FLAG (ospf->config, OSPF_RFC1583_COMPATIBLE))
paul718e3742002-12-13 20:15:29 +0000726 {
paul6d1fab62003-06-22 08:28:18 +0000727 ret = ospf_asbr_route_cmp (ospf, r1->u.ext.asbr, r2->u.ext.asbr);
paul718e3742002-12-13 20:15:29 +0000728 if (ret != 0)
729 return ret;
730 }
731 break;
732 case OSPF_PATH_TYPE2_EXTERNAL:
733 if ((ret = (r1->u.ext.type2_cost - r2->u.ext.type2_cost)))
734 return ret;
735
paul6d1fab62003-06-22 08:28:18 +0000736 if (!CHECK_FLAG (ospf->config, OSPF_RFC1583_COMPATIBLE))
paul718e3742002-12-13 20:15:29 +0000737 {
paul6d1fab62003-06-22 08:28:18 +0000738 ret = ospf_asbr_route_cmp (ospf, r1->u.ext.asbr, r2->u.ext.asbr);
paul718e3742002-12-13 20:15:29 +0000739 if (ret != 0)
740 return ret;
741 }
742 break;
743 }
744
745 /* Anyway, compare the costs. */
746 return (r1->cost - r2->cost);
747}
748
paul4dadc292005-05-06 21:37:42 +0000749static int
paul718e3742002-12-13 20:15:29 +0000750ospf_path_exist (struct list *plist, struct in_addr nexthop,
751 struct ospf_interface *oi)
752{
paul1eb8ef22005-04-07 07:30:20 +0000753 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000754 struct ospf_path *path;
755
paul1eb8ef22005-04-07 07:30:20 +0000756 for (ALL_LIST_ELEMENTS (plist, node, nnode, path))
Joakim Tjernlunda8ba8472009-07-27 12:42:34 +0200757 if (IPV4_ADDR_SAME (&path->nexthop, &nexthop) &&
758 path->ifindex == oi->ifp->ifindex)
paul1eb8ef22005-04-07 07:30:20 +0000759 return 1;
paul718e3742002-12-13 20:15:29 +0000760
paul718e3742002-12-13 20:15:29 +0000761 return 0;
762}
763
764void
765ospf_route_copy_nexthops_from_vertex (struct ospf_route *to,
766 struct vertex *v)
767{
paul1eb8ef22005-04-07 07:30:20 +0000768 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000769 struct ospf_path *path;
770 struct vertex_nexthop *nexthop;
pauleb3da6d2005-10-18 04:20:33 +0000771 struct vertex_parent *vp;
paul718e3742002-12-13 20:15:29 +0000772
paul96735ee2003-08-10 02:51:22 +0000773 assert (to->paths);
paul718e3742002-12-13 20:15:29 +0000774
pauleb3da6d2005-10-18 04:20:33 +0000775 for (ALL_LIST_ELEMENTS_RO (v->parents, node, vp))
paul718e3742002-12-13 20:15:29 +0000776 {
pauleb3da6d2005-10-18 04:20:33 +0000777 nexthop = vp->nexthop;
778
paul718e3742002-12-13 20:15:29 +0000779 if (nexthop->oi != NULL)
780 {
paul96735ee2003-08-10 02:51:22 +0000781 if (! ospf_path_exist (to->paths, nexthop->router, nexthop->oi))
paul718e3742002-12-13 20:15:29 +0000782 {
783 path = ospf_path_new ();
784 path->nexthop = nexthop->router;
Joakim Tjernlunda8ba8472009-07-27 12:42:34 +0200785 path->ifindex = nexthop->oi->ifp->ifindex;
paul96735ee2003-08-10 02:51:22 +0000786 listnode_add (to->paths, path);
paul718e3742002-12-13 20:15:29 +0000787 }
788 }
789 }
790}
791
792struct ospf_path *
hasso52dc7ee2004-09-23 19:18:23 +0000793ospf_path_lookup (struct list *plist, struct ospf_path *path)
paul718e3742002-12-13 20:15:29 +0000794{
hasso52dc7ee2004-09-23 19:18:23 +0000795 struct listnode *node;
paul1eb8ef22005-04-07 07:30:20 +0000796 struct ospf_path *op;
paul718e3742002-12-13 20:15:29 +0000797
paul1eb8ef22005-04-07 07:30:20 +0000798 for (ALL_LIST_ELEMENTS_RO (plist, node, op))
Joakim Tjernlund77a1c4e2009-02-01 11:12:11 +0100799 {
800 if (!IPV4_ADDR_SAME (&op->nexthop, &path->nexthop))
801 continue;
802 if (!IPV4_ADDR_SAME (&op->adv_router, &path->adv_router))
803 continue;
Joakim Tjernlunda8ba8472009-07-27 12:42:34 +0200804 if (op->ifindex != path->ifindex)
Joakim Tjernlund77a1c4e2009-02-01 11:12:11 +0100805 continue;
806 return op;
807 }
paul718e3742002-12-13 20:15:29 +0000808 return NULL;
809}
810
811void
hasso52dc7ee2004-09-23 19:18:23 +0000812ospf_route_copy_nexthops (struct ospf_route *to, struct list *from)
paul718e3742002-12-13 20:15:29 +0000813{
paul1eb8ef22005-04-07 07:30:20 +0000814 struct listnode *node, *nnode;
815 struct ospf_path *path;
paul718e3742002-12-13 20:15:29 +0000816
paul96735ee2003-08-10 02:51:22 +0000817 assert (to->paths);
paul718e3742002-12-13 20:15:29 +0000818
paul1eb8ef22005-04-07 07:30:20 +0000819 for (ALL_LIST_ELEMENTS (from, node, nnode, path))
paul718e3742002-12-13 20:15:29 +0000820 /* The same routes are just discarded. */
paul1eb8ef22005-04-07 07:30:20 +0000821 if (!ospf_path_lookup (to->paths, path))
822 listnode_add (to->paths, ospf_path_dup (path));
paul718e3742002-12-13 20:15:29 +0000823}
824
825void
hasso52dc7ee2004-09-23 19:18:23 +0000826ospf_route_subst_nexthops (struct ospf_route *to, struct list *from)
paul718e3742002-12-13 20:15:29 +0000827{
paul718e3742002-12-13 20:15:29 +0000828
paul96735ee2003-08-10 02:51:22 +0000829 list_delete_all_node (to->paths);
paul718e3742002-12-13 20:15:29 +0000830 ospf_route_copy_nexthops (to, from);
831}
832
833void
834ospf_route_subst (struct route_node *rn, struct ospf_route *new_or,
835 struct ospf_route *over)
836{
837 route_lock_node (rn);
838 ospf_route_free (rn->info);
839
paul96735ee2003-08-10 02:51:22 +0000840 ospf_route_copy_nexthops (new_or, over->paths);
paul718e3742002-12-13 20:15:29 +0000841 rn->info = new_or;
842 route_unlock_node (rn);
843}
844
845void
846ospf_route_add (struct route_table *rt, struct prefix_ipv4 *p,
847 struct ospf_route *new_or, struct ospf_route *over)
848{
849 struct route_node *rn;
850
851 rn = route_node_get (rt, (struct prefix *) p);
852
paul96735ee2003-08-10 02:51:22 +0000853 ospf_route_copy_nexthops (new_or, over->paths);
paul718e3742002-12-13 20:15:29 +0000854
855 if (rn->info)
856 {
857 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000858 zlog_debug ("ospf_route_add(): something's wrong !");
paul718e3742002-12-13 20:15:29 +0000859 route_unlock_node (rn);
860 return;
861 }
862
863 rn->info = new_or;
864}
865
866void
867ospf_prune_unreachable_networks (struct route_table *rt)
868{
869 struct route_node *rn, *next;
870 struct ospf_route *or;
871
872 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000873 zlog_debug ("Pruning unreachable networks");
paul718e3742002-12-13 20:15:29 +0000874
875 for (rn = route_top (rt); rn; rn = next)
876 {
877 next = route_next (rn);
878 if (rn->info != NULL)
879 {
880 or = rn->info;
paul96735ee2003-08-10 02:51:22 +0000881 if (listcount (or->paths) == 0)
paul718e3742002-12-13 20:15:29 +0000882 {
883 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000884 zlog_debug ("Pruning route to %s/%d",
paul718e3742002-12-13 20:15:29 +0000885 inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen);
886
887 ospf_route_free (or);
888 rn->info = NULL;
889 route_unlock_node (rn);
890 }
891 }
892 }
893}
894
895void
896ospf_prune_unreachable_routers (struct route_table *rtrs)
897{
898 struct route_node *rn, *next;
899 struct ospf_route *or;
paul1eb8ef22005-04-07 07:30:20 +0000900 struct listnode *node, *nnode;
hasso52dc7ee2004-09-23 19:18:23 +0000901 struct list *paths;
paul718e3742002-12-13 20:15:29 +0000902
903 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000904 zlog_debug ("Pruning unreachable routers");
paul718e3742002-12-13 20:15:29 +0000905
906 for (rn = route_top (rtrs); rn; rn = next)
907 {
908 next = route_next (rn);
909 if ((paths = rn->info) == NULL)
910 continue;
911
paul1eb8ef22005-04-07 07:30:20 +0000912 for (ALL_LIST_ELEMENTS (paths, node, nnode, or))
paul718e3742002-12-13 20:15:29 +0000913 {
paul96735ee2003-08-10 02:51:22 +0000914 if (listcount (or->paths) == 0)
paul718e3742002-12-13 20:15:29 +0000915 {
916 if (IS_DEBUG_OSPF_EVENT)
917 {
ajs2a42e282004-12-08 18:43:03 +0000918 zlog_debug ("Pruning route to rtr %s",
paul718e3742002-12-13 20:15:29 +0000919 inet_ntoa (rn->p.u.prefix4));
ajs2a42e282004-12-08 18:43:03 +0000920 zlog_debug (" via area %s",
paul718e3742002-12-13 20:15:29 +0000921 inet_ntoa (or->u.std.area_id));
922 }
923
924 listnode_delete (paths, or);
925 ospf_route_free (or);
926 }
927 }
928
929 if (listcount (paths) == 0)
930 {
931 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000932 zlog_debug ("Pruning router node %s", inet_ntoa (rn->p.u.prefix4));
paul718e3742002-12-13 20:15:29 +0000933
934 list_delete (paths);
935 rn->info = NULL;
936 route_unlock_node (rn);
937 }
938 }
939}
940
941int
942ospf_add_discard_route (struct route_table *rt, struct ospf_area *area,
943 struct prefix_ipv4 *p)
944{
945 struct route_node *rn;
946 struct ospf_route *or, *new_or;
947
948 rn = route_node_get (rt, (struct prefix *) p);
949
950 if (rn == NULL)
951 {
952 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000953 zlog_debug ("ospf_add_discard_route(): router installation error");
paul718e3742002-12-13 20:15:29 +0000954 return 0;
955 }
956
957 if (rn->info) /* If the route to the same destination is found */
958 {
959 route_unlock_node (rn);
960
961 or = rn->info;
962
963 if (or->path_type == OSPF_PATH_INTRA_AREA)
964 {
965 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000966 zlog_debug ("ospf_add_discard_route(): "
paul718e3742002-12-13 20:15:29 +0000967 "an intra-area route exists");
968 return 0;
969 }
970
971 if (or->type == OSPF_DESTINATION_DISCARD)
972 {
973 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000974 zlog_debug ("ospf_add_discard_route(): "
paul718e3742002-12-13 20:15:29 +0000975 "discard entry already installed");
976 return 0;
977 }
978
979 ospf_route_free (rn->info);
980 }
981
JR Rivers8fc9e002012-09-24 17:26:46 +0000982 if (IS_DEBUG_OSPF_EVENT)
983 zlog_debug ("ospf_add_discard_route(): "
984 "adding %s/%d", inet_ntoa (p->prefix), p->prefixlen);
985
paul718e3742002-12-13 20:15:29 +0000986 new_or = ospf_route_new ();
987 new_or->type = OSPF_DESTINATION_DISCARD;
988 new_or->id.s_addr = 0;
989 new_or->cost = 0;
990 new_or->u.std.area_id = area->area_id;
paul718e3742002-12-13 20:15:29 +0000991 new_or->u.std.external_routing = area->external_routing;
paul718e3742002-12-13 20:15:29 +0000992 new_or->path_type = OSPF_PATH_INTER_AREA;
993 rn->info = new_or;
994
995 ospf_zebra_add_discard (p);
996
997 return 1;
998}
999
1000void
JR Rivers8fc9e002012-09-24 17:26:46 +00001001ospf_delete_discard_route (struct route_table *rt, struct prefix_ipv4 *p)
paul718e3742002-12-13 20:15:29 +00001002{
JR Rivers8fc9e002012-09-24 17:26:46 +00001003 struct route_node *rn;
1004 struct ospf_route *or;
1005
1006 if (IS_DEBUG_OSPF_EVENT)
1007 zlog_debug ("ospf_delete_discard_route(): "
1008 "deleting %s/%d", inet_ntoa (p->prefix), p->prefixlen);
1009
1010 rn = route_node_lookup (rt, (struct prefix*)p);
1011
1012 if (rn == NULL)
1013 {
1014 if (IS_DEBUG_OSPF_EVENT)
1015 zlog_debug("ospf_delete_discard_route(): no route found");
1016 return;
1017 }
1018
1019 or = rn->info;
1020
1021 if (or->path_type == OSPF_PATH_INTRA_AREA)
1022 {
1023 if (IS_DEBUG_OSPF_EVENT)
1024 zlog_debug ("ospf_delete_discard_route(): "
1025 "an intra-area route exists");
1026 return;
1027 }
1028
1029 if (or->type != OSPF_DESTINATION_DISCARD)
1030 {
1031 if (IS_DEBUG_OSPF_EVENT)
1032 zlog_debug ("ospf_delete_discard_route(): "
1033 "not a discard entry");
1034 return;
1035 }
1036
1037 /* free the route entry and the route node */
1038 ospf_route_free (rn->info);
1039
1040 rn->info = NULL;
1041 route_unlock_node (rn);
1042 route_unlock_node (rn);
1043
1044 /* remove the discard entry from the rib */
paul718e3742002-12-13 20:15:29 +00001045 ospf_zebra_delete_discard(p);
JR Rivers8fc9e002012-09-24 17:26:46 +00001046
1047 return;
paul718e3742002-12-13 20:15:29 +00001048}
1049