]> git.proxmox.com Git - mirror_frr.git/blob - ospfd/ospf_route.c
Merge remote-tracking branch 'origin/stable/3.0'
[mirror_frr.git] / ospfd / ospf_route.c
1 /*
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 along
18 * with this program; see the file COPYING; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22 #include <zebra.h>
23
24 #include "prefix.h"
25 #include "table.h"
26 #include "memory.h"
27 #include "linklist.h"
28 #include "log.h"
29 #include "if.h"
30 #include "command.h"
31 #include "sockunion.h"
32
33 #include "ospfd/ospfd.h"
34 #include "ospfd/ospf_interface.h"
35 #include "ospfd/ospf_asbr.h"
36 #include "ospfd/ospf_lsa.h"
37 #include "ospfd/ospf_route.h"
38 #include "ospfd/ospf_spf.h"
39 #include "ospfd/ospf_zebra.h"
40 #include "ospfd/ospf_dump.h"
41
42 struct ospf_route *
43 ospf_route_new ()
44 {
45 struct ospf_route *new;
46
47 new = XCALLOC (MTYPE_OSPF_ROUTE, sizeof (struct ospf_route));
48
49 new->paths = list_new ();
50 new->paths->del = (void (*) (void *))ospf_path_free;
51
52 return new;
53 }
54
55 void
56 ospf_route_free (struct ospf_route *or)
57 {
58 if (or->paths)
59 list_delete (or->paths);
60
61 XFREE (MTYPE_OSPF_ROUTE, or);
62 }
63
64 struct ospf_path *
65 ospf_path_new ()
66 {
67 struct ospf_path *new;
68
69 new = XCALLOC (MTYPE_OSPF_PATH, sizeof (struct ospf_path));
70
71 return new;
72 }
73
74 static struct ospf_path *
75 ospf_path_dup (struct ospf_path *path)
76 {
77 struct ospf_path *new;
78
79 new = ospf_path_new ();
80 memcpy (new, path, sizeof (struct ospf_path));
81
82 return new;
83 }
84
85 void
86 ospf_path_free (struct ospf_path *op)
87 {
88 XFREE (MTYPE_OSPF_PATH, op);
89 }
90
91 void
92 ospf_route_delete (struct route_table *rt)
93 {
94 struct route_node *rn;
95 struct ospf_route *or;
96
97 for (rn = route_top (rt); rn; rn = route_next (rn))
98 if ((or = rn->info) != NULL)
99 {
100 if (or->type == OSPF_DESTINATION_NETWORK)
101 ospf_zebra_delete ((struct prefix_ipv4 *) &rn->p,
102 or);
103 else if (or->type == OSPF_DESTINATION_DISCARD)
104 ospf_zebra_delete_discard ((struct prefix_ipv4 *) &rn->p);
105 }
106 }
107
108 void
109 ospf_route_table_free (struct route_table *rt)
110 {
111 struct route_node *rn;
112 struct ospf_route *or;
113
114 for (rn = route_top (rt); rn; rn = route_next (rn))
115 if ((or = rn->info) != NULL)
116 {
117 ospf_route_free (or);
118
119 rn->info = NULL;
120 route_unlock_node (rn);
121 }
122
123 route_table_finish (rt);
124 }
125
126 /* If a prefix exists in the new routing table, then return 1,
127 otherwise return 0. Since the ZEBRA-RIB does an implicit
128 withdraw, it is not necessary to send a delete, an add later
129 will act like an implicit delete. */
130 static int
131 ospf_route_exist_new_table (struct route_table *rt, struct prefix_ipv4 *prefix)
132 {
133 struct route_node *rn;
134
135 assert (rt);
136 assert (prefix);
137
138 rn = route_node_lookup (rt, (struct prefix *) prefix);
139 if (!rn) {
140 return 0;
141 }
142 route_unlock_node (rn);
143
144 if (!rn->info) {
145 return 0;
146 }
147
148 return 1;
149 }
150
151 /* If a prefix and a nexthop match any route in the routing table,
152 then return 1, otherwise return 0. */
153 int
154 ospf_route_match_same (struct route_table *rt, struct prefix_ipv4 *prefix,
155 struct ospf_route *newor)
156 {
157 struct route_node *rn;
158 struct ospf_route *or;
159 struct ospf_path *op;
160 struct ospf_path *newop;
161 struct listnode *n1;
162 struct listnode *n2;
163
164 if (! rt || ! prefix)
165 return 0;
166
167 rn = route_node_lookup (rt, (struct prefix *) prefix);
168 if (! rn || ! rn->info)
169 return 0;
170
171 route_unlock_node (rn);
172
173 or = rn->info;
174 if (or->type == newor->type && or->cost == newor->cost)
175 {
176 if (or->type == OSPF_DESTINATION_NETWORK)
177 {
178 if (or->paths->count != newor->paths->count)
179 return 0;
180
181 /* Check each path. */
182 for (n1 = listhead (or->paths), n2 = listhead (newor->paths);
183 n1 && n2; n1 = listnextnode (n1), n2 = listnextnode (n2))
184 {
185 op = listgetdata (n1);
186 newop = listgetdata (n2);
187
188 if (! IPV4_ADDR_SAME (&op->nexthop, &newop->nexthop))
189 return 0;
190 if (op->ifindex != newop->ifindex)
191 return 0;
192 }
193 return 1;
194 }
195 else if (prefix_same (&rn->p, (struct prefix *) prefix))
196 return 1;
197 }
198 return 0;
199 }
200
201 /* delete routes generated from AS-External routes if there is a inter/intra
202 * area route
203 */
204 static void
205 ospf_route_delete_same_ext(struct route_table *external_routes,
206 struct route_table *routes)
207 {
208 struct route_node *rn,
209 *ext_rn;
210
211 if ( (external_routes == NULL) || (routes == NULL) )
212 return;
213
214 /* Remove deleted routes */
215 for ( rn = route_top (routes); rn; rn = route_next (rn) )
216 {
217 if (rn && rn->info)
218 {
219 struct prefix_ipv4 *p = (struct prefix_ipv4 *)(&rn->p);
220 if ( (ext_rn = route_node_lookup (external_routes, (struct prefix *)p)) )
221 {
222 if (ext_rn->info)
223 {
224 ospf_zebra_delete (p, ext_rn->info);
225 ospf_route_free( ext_rn->info);
226 ext_rn->info = NULL;
227 }
228 route_unlock_node (ext_rn);
229 }
230 }
231 }
232 }
233
234 /* rt: Old, cmprt: New */
235 static void
236 ospf_route_delete_uniq (struct route_table *rt, struct route_table *cmprt)
237 {
238 struct route_node *rn;
239 struct ospf_route *or;
240
241 for (rn = route_top (rt); rn; rn = route_next (rn))
242 if ((or = rn->info) != NULL)
243 if (or->path_type == OSPF_PATH_INTRA_AREA ||
244 or->path_type == OSPF_PATH_INTER_AREA)
245 {
246 if (or->type == OSPF_DESTINATION_NETWORK)
247 {
248 if (! ospf_route_exist_new_table (cmprt,
249 (struct prefix_ipv4 *) &rn->p))
250 ospf_zebra_delete ((struct prefix_ipv4 *) &rn->p, or);
251 }
252 else if (or->type == OSPF_DESTINATION_DISCARD)
253 if (! ospf_route_exist_new_table (cmprt,
254 (struct prefix_ipv4 *) &rn->p))
255 ospf_zebra_delete_discard ((struct prefix_ipv4 *) &rn->p);
256 }
257 }
258
259 /* Install routes to table. */
260 void
261 ospf_route_install (struct ospf *ospf, struct route_table *rt)
262 {
263 struct route_node *rn;
264 struct ospf_route *or;
265
266 /* rt contains new routing table, new_table contains an old one.
267 updating pointers */
268 if (ospf->old_table)
269 ospf_route_table_free (ospf->old_table);
270
271 ospf->old_table = ospf->new_table;
272 ospf->new_table = rt;
273
274 /* Delete old routes. */
275 if (ospf->old_table)
276 ospf_route_delete_uniq (ospf->old_table, rt);
277 if (ospf->old_external_route)
278 ospf_route_delete_same_ext (ospf->old_external_route, rt);
279
280 /* Install new routes. */
281 for (rn = route_top (rt); rn; rn = route_next (rn))
282 if ((or = rn->info) != NULL)
283 {
284 if (or->type == OSPF_DESTINATION_NETWORK)
285 {
286 if (! ospf_route_match_same (ospf->old_table,
287 (struct prefix_ipv4 *)&rn->p, or))
288 ospf_zebra_add ((struct prefix_ipv4 *) &rn->p, or);
289 }
290 else if (or->type == OSPF_DESTINATION_DISCARD)
291 if (! ospf_route_match_same (ospf->old_table,
292 (struct prefix_ipv4 *) &rn->p, or))
293 ospf_zebra_add_discard ((struct prefix_ipv4 *) &rn->p);
294 }
295 }
296
297 /* RFC2328 16.1. (4). For "router". */
298 void
299 ospf_intra_add_router (struct route_table *rt, struct vertex *v,
300 struct ospf_area *area)
301 {
302 struct route_node *rn;
303 struct ospf_route *or;
304 struct prefix_ipv4 p;
305 struct router_lsa *lsa;
306
307 if (IS_DEBUG_OSPF_EVENT)
308 zlog_debug ("ospf_intra_add_router: Start");
309
310 lsa = (struct router_lsa *) v->lsa;
311
312 if (IS_DEBUG_OSPF_EVENT)
313 zlog_debug ("ospf_intra_add_router: LS ID: %s",
314 inet_ntoa (lsa->header.id));
315
316 if (!OSPF_IS_AREA_BACKBONE(area))
317 ospf_vl_up_check (area, lsa->header.id, v);
318
319 if (!CHECK_FLAG (lsa->flags, ROUTER_LSA_SHORTCUT))
320 area->shortcut_capability = 0;
321
322 /* If the newly added vertex is an area border router or AS boundary
323 router, a routing table entry is added whose destination type is
324 "router". */
325 if (! IS_ROUTER_LSA_BORDER (lsa) && ! IS_ROUTER_LSA_EXTERNAL (lsa))
326 {
327 if (IS_DEBUG_OSPF_EVENT)
328 zlog_debug ("ospf_intra_add_router: "
329 "this router is neither ASBR nor ABR, skipping it");
330 return;
331 }
332
333 /* Update ABR and ASBR count in this area. */
334 if (IS_ROUTER_LSA_BORDER (lsa))
335 area->abr_count++;
336 if (IS_ROUTER_LSA_EXTERNAL (lsa))
337 area->asbr_count++;
338
339 /* The Options field found in the associated router-LSA is copied
340 into the routing table entry's Optional capabilities field. Call
341 the newly added vertex Router X. */
342 or = ospf_route_new ();
343
344 or->id = v->id;
345 or->u.std.area_id = area->area_id;
346 or->u.std.external_routing = area->external_routing;
347 or->path_type = OSPF_PATH_INTRA_AREA;
348 or->cost = v->distance;
349 or->type = OSPF_DESTINATION_ROUTER;
350 or->u.std.origin = (struct lsa_header *) lsa;
351 or->u.std.options = lsa->header.options;
352 or->u.std.flags = lsa->flags;
353
354 /* If Router X is the endpoint of one of the calculating router's
355 virtual links, and the virtual link uses Area A as Transit area:
356 the virtual link is declared up, the IP address of the virtual
357 interface is set to the IP address of the outgoing interface
358 calculated above for Router X, and the virtual neighbor's IP
359 address is set to Router X's interface address (contained in
360 Router X's router-LSA) that points back to the root of the
361 shortest- path tree; equivalently, this is the interface that
362 points back to Router X's parent vertex on the shortest-path tree
363 (similar to the calculation in Section 16.1.1). */
364
365 p.family = AF_INET;
366 p.prefix = v->id;
367 p.prefixlen = IPV4_MAX_BITLEN;
368
369 if (IS_DEBUG_OSPF_EVENT)
370 zlog_debug ("ospf_intra_add_router: talking about %s/%d",
371 inet_ntoa (p.prefix), p.prefixlen);
372
373 rn = route_node_get (rt, (struct prefix *) &p);
374
375 /* Note that we keep all routes to ABRs and ASBRs, not only the best */
376 if (rn->info == NULL)
377 rn->info = list_new ();
378 else
379 route_unlock_node (rn);
380
381 ospf_route_copy_nexthops_from_vertex (or, v);
382
383 listnode_add (rn->info, or);
384
385 if (IS_DEBUG_OSPF_EVENT)
386 zlog_debug ("ospf_intra_add_router: Stop");
387 }
388
389 /* RFC2328 16.1. (4). For transit network. */
390 void
391 ospf_intra_add_transit (struct route_table *rt, struct vertex *v,
392 struct ospf_area *area)
393 {
394 struct route_node *rn;
395 struct ospf_route *or;
396 struct prefix_ipv4 p;
397 struct network_lsa *lsa;
398
399 lsa = (struct network_lsa*) v->lsa;
400
401 /* If the newly added vertex is a transit network, the routing table
402 entry for the network is located. The entry's Destination ID is
403 the IP network number, which can be obtained by masking the
404 Vertex ID (Link State ID) with its associated subnet mask (found
405 in the body of the associated network-LSA). */
406 p.family = AF_INET;
407 p.prefix = v->id;
408 p.prefixlen = ip_masklen (lsa->mask);
409 apply_mask_ipv4 (&p);
410
411 rn = route_node_get (rt, (struct prefix *) &p);
412
413 /* If the routing table entry already exists (i.e., there is already
414 an intra-area route to the destination installed in the routing
415 table), multiple vertices have mapped to the same IP network.
416 For example, this can occur when a new Designated Router is being
417 established. In this case, the current routing table entry
418 should be overwritten if and only if the newly found path is just
419 as short and the current routing table entry's Link State Origin
420 has a smaller Link State ID than the newly added vertex' LSA. */
421 if (rn->info)
422 {
423 struct ospf_route *cur_or;
424
425 route_unlock_node (rn);
426 cur_or = rn->info;
427
428 if (v->distance > cur_or->cost ||
429 IPV4_ADDR_CMP (&cur_or->u.std.origin->id, &lsa->header.id) > 0)
430 return;
431
432 ospf_route_free (rn->info);
433 }
434
435 or = ospf_route_new ();
436
437 or->id = v->id;
438 or->u.std.area_id = area->area_id;
439 or->u.std.external_routing = area->external_routing;
440 or->path_type = OSPF_PATH_INTRA_AREA;
441 or->cost = v->distance;
442 or->type = OSPF_DESTINATION_NETWORK;
443 or->u.std.origin = (struct lsa_header *) lsa;
444
445 ospf_route_copy_nexthops_from_vertex (or, v);
446
447 rn->info = or;
448 }
449
450 /* RFC2328 16.1. second stage. */
451 void
452 ospf_intra_add_stub (struct route_table *rt, struct router_lsa_link *link,
453 struct vertex *v, struct ospf_area *area,
454 int parent_is_root, int lsa_pos)
455 {
456 u_int32_t cost;
457 struct route_node *rn;
458 struct ospf_route *or;
459 struct prefix_ipv4 p;
460 struct router_lsa *lsa;
461 struct ospf_interface *oi;
462 struct ospf_path *path;
463
464 if (IS_DEBUG_OSPF_EVENT)
465 zlog_debug ("ospf_intra_add_stub(): Start");
466
467 lsa = (struct router_lsa *) v->lsa;
468
469 p.family = AF_INET;
470 p.prefix = link->link_id;
471 p.prefixlen = ip_masklen (link->link_data);
472 apply_mask_ipv4 (&p);
473
474 if (IS_DEBUG_OSPF_EVENT)
475 zlog_debug ("ospf_intra_add_stub(): processing route to %s/%d",
476 inet_ntoa (p.prefix), p.prefixlen);
477
478 /* (1) Calculate the distance D of stub network from the root. D is
479 equal to the distance from the root to the router vertex
480 (calculated in stage 1), plus the stub network link's advertised
481 cost. */
482 cost = v->distance + ntohs (link->m[0].metric);
483
484 if (IS_DEBUG_OSPF_EVENT)
485 zlog_debug ("ospf_intra_add_stub(): calculated cost is %d + %d = %d",
486 v->distance, ntohs(link->m[0].metric), cost);
487
488 /* PtP links with /32 masks adds host routes to remote, directly
489 * connected hosts, see RFC 2328, 12.4.1.1, Option 1.
490 * Such routes can just be ignored for the sake of tidyness.
491 */
492 if (parent_is_root && link->link_data.s_addr == 0xffffffff &&
493 ospf_if_lookup_by_local_addr (area->ospf, NULL, link->link_id))
494 {
495 if (IS_DEBUG_OSPF_EVENT)
496 zlog_debug ("%s: ignoring host route %s/32 to self.",
497 __func__, inet_ntoa (link->link_id));
498 return;
499 }
500
501 rn = route_node_get (rt, (struct prefix *) &p);
502
503 /* Lookup current routing table. */
504 if (rn->info)
505 {
506 struct ospf_route *cur_or;
507
508 route_unlock_node (rn);
509
510 cur_or = rn->info;
511
512 if (IS_DEBUG_OSPF_EVENT)
513 zlog_debug ("ospf_intra_add_stub(): "
514 "another route to the same prefix found with cost %u",
515 cur_or->cost);
516
517 /* Compare this distance to the current best cost to the stub
518 network. This is done by looking up the stub network's
519 current routing table entry. If the calculated distance D is
520 larger, go on to examine the next stub network link in the
521 LSA. */
522 if (cost > cur_or->cost)
523 {
524 if (IS_DEBUG_OSPF_EVENT)
525 zlog_debug ("ospf_intra_add_stub(): old route is better, exit");
526 return;
527 }
528
529 /* (2) If this step is reached, the stub network's routing table
530 entry must be updated. Calculate the set of next hops that
531 would result from using the stub network link. This
532 calculation is shown in Section 16.1.1; input to this
533 calculation is the destination (the stub network) and the
534 parent vertex (the router vertex). If the distance D is the
535 same as the current routing table cost, simply add this set
536 of next hops to the routing table entry's list of next hops.
537 In this case, the routing table already has a Link State
538 Origin. If this Link State Origin is a router-LSA whose Link
539 State ID is smaller than V's Router ID, reset the Link State
540 Origin to V's router-LSA. */
541
542 if (cost == cur_or->cost)
543 {
544 if (IS_DEBUG_OSPF_EVENT)
545 zlog_debug ("ospf_intra_add_stub(): routes are equal, merge");
546
547 ospf_route_copy_nexthops_from_vertex (cur_or, v);
548
549 if (IPV4_ADDR_CMP (&cur_or->u.std.origin->id, &lsa->header.id) < 0)
550 cur_or->u.std.origin = (struct lsa_header *) lsa;
551 return;
552 }
553
554 /* Otherwise D is smaller than the routing table cost.
555 Overwrite the current routing table entry by setting the
556 routing table entry's cost to D, and by setting the entry's
557 list of next hops to the newly calculated set. Set the
558 routing table entry's Link State Origin to V's router-LSA.
559 Then go on to examine the next stub network link. */
560
561 if (cost < cur_or->cost)
562 {
563 if (IS_DEBUG_OSPF_EVENT)
564 zlog_debug ("ospf_intra_add_stub(): new route is better, set it");
565
566 cur_or->cost = cost;
567
568 list_delete_all_node (cur_or->paths);
569
570 ospf_route_copy_nexthops_from_vertex (cur_or, v);
571
572 cur_or->u.std.origin = (struct lsa_header *) lsa;
573 return;
574 }
575 }
576
577 if (IS_DEBUG_OSPF_EVENT)
578 zlog_debug ("ospf_intra_add_stub(): installing new route");
579
580 or = ospf_route_new ();
581
582 or->id = v->id;
583 or->u.std.area_id = area->area_id;
584 or->u.std.external_routing = area->external_routing;
585 or->path_type = OSPF_PATH_INTRA_AREA;
586 or->cost = cost;
587 or->type = OSPF_DESTINATION_NETWORK;
588 or->u.std.origin = (struct lsa_header *) lsa;
589
590 /* Nexthop is depend on connection type. */
591 if (v != area->spf)
592 {
593 if (IS_DEBUG_OSPF_EVENT)
594 zlog_debug ("ospf_intra_add_stub(): this network is on remote router");
595 ospf_route_copy_nexthops_from_vertex (or, v);
596 }
597 else
598 {
599 if (IS_DEBUG_OSPF_EVENT)
600 zlog_debug ("ospf_intra_add_stub(): this network is on this router");
601
602 if ((oi = ospf_if_lookup_by_lsa_pos (area, lsa_pos)))
603 {
604 if (IS_DEBUG_OSPF_EVENT)
605 zlog_debug ("ospf_intra_add_stub(): the interface is %s",
606 IF_NAME (oi));
607
608 path = ospf_path_new ();
609 path->nexthop.s_addr = 0;
610 path->ifindex = oi->ifp->ifindex;
611 if (CHECK_FLAG(oi->connected->flags, ZEBRA_IFA_UNNUMBERED))
612 path->unnumbered = 1;
613 listnode_add (or->paths, path);
614 }
615 else
616 {
617 if (IS_DEBUG_OSPF_EVENT)
618 zlog_debug ("ospf_intra_add_stub(): where's the interface ?");
619 }
620 }
621
622 rn->info = or;
623
624 if (IS_DEBUG_OSPF_EVENT)
625 zlog_debug("ospf_intra_add_stub(): Stop");
626 }
627
628 const char *ospf_path_type_str[] =
629 {
630 "unknown-type",
631 "intra-area",
632 "inter-area",
633 "type1-external",
634 "type2-external"
635 };
636
637 void
638 ospf_route_table_dump (struct route_table *rt)
639 {
640 struct route_node *rn;
641 struct ospf_route *or;
642 char buf1[BUFSIZ];
643 char buf2[BUFSIZ];
644 struct listnode *pnode;
645 struct ospf_path *path;
646
647 #if 0
648 zlog_debug ("Type Dest Area Path Type Cost Next Adv.");
649 zlog_debug (" Hop(s) Router(s)");
650 #endif /* 0 */
651
652 zlog_debug ("========== OSPF routing table ==========");
653 for (rn = route_top (rt); rn; rn = route_next (rn))
654 if ((or = rn->info) != NULL)
655 {
656 if (or->type == OSPF_DESTINATION_NETWORK)
657 {
658 zlog_debug ("N %s/%d\t%s\t%s\t%d",
659 inet_ntop (AF_INET, &rn->p.u.prefix4, buf1, BUFSIZ),
660 rn->p.prefixlen,
661 inet_ntop (AF_INET, &or->u.std.area_id, buf2,
662 BUFSIZ),
663 ospf_path_type_str[or->path_type],
664 or->cost);
665 for (ALL_LIST_ELEMENTS_RO (or->paths, pnode, path))
666 zlog_debug (" -> %s", inet_ntoa (path->nexthop));
667 }
668 else
669 zlog_debug ("R %s\t%s\t%s\t%d",
670 inet_ntop (AF_INET, &rn->p.u.prefix4, buf1, BUFSIZ),
671 inet_ntop (AF_INET, &or->u.std.area_id, buf2,
672 BUFSIZ),
673 ospf_path_type_str[or->path_type],
674 or->cost);
675 }
676 zlog_debug ("========================================");
677 }
678
679 /* This is 16.4.1 implementation.
680 o Intra-area paths using non-backbone areas are always the most preferred.
681 o The other paths, intra-area backbone paths and inter-area paths,
682 are of equal preference. */
683 static int
684 ospf_asbr_route_cmp (struct ospf *ospf, struct ospf_route *r1,
685 struct ospf_route *r2)
686 {
687 u_char r1_type, r2_type;
688
689 r1_type = r1->path_type;
690 r2_type = r2->path_type;
691
692 /* r1/r2 itself is backbone, and it's Inter-area path. */
693 if (OSPF_IS_AREA_ID_BACKBONE (r1->u.std.area_id))
694 r1_type = OSPF_PATH_INTER_AREA;
695 if (OSPF_IS_AREA_ID_BACKBONE (r2->u.std.area_id))
696 r2_type = OSPF_PATH_INTER_AREA;
697
698 return (r1_type - r2_type);
699 }
700
701 /* Compare two routes.
702 ret < 0 -- r1 is better.
703 ret == 0 -- r1 and r2 are the same.
704 ret > 0 -- r2 is better. */
705 int
706 ospf_route_cmp (struct ospf *ospf, struct ospf_route *r1,
707 struct ospf_route *r2)
708 {
709 int ret = 0;
710
711 /* Path types of r1 and r2 are not the same. */
712 if ((ret = (r1->path_type - r2->path_type)))
713 return ret;
714
715 if (IS_DEBUG_OSPF_EVENT)
716 zlog_debug ("Route[Compare]: Path types are the same.");
717 /* Path types are the same, compare any cost. */
718 switch (r1->path_type)
719 {
720 case OSPF_PATH_INTRA_AREA:
721 case OSPF_PATH_INTER_AREA:
722 break;
723 case OSPF_PATH_TYPE1_EXTERNAL:
724 if (!CHECK_FLAG (ospf->config, OSPF_RFC1583_COMPATIBLE))
725 {
726 ret = ospf_asbr_route_cmp (ospf, r1->u.ext.asbr, r2->u.ext.asbr);
727 if (ret != 0)
728 return ret;
729 }
730 break;
731 case OSPF_PATH_TYPE2_EXTERNAL:
732 if ((ret = (r1->u.ext.type2_cost - r2->u.ext.type2_cost)))
733 return ret;
734
735 if (!CHECK_FLAG (ospf->config, OSPF_RFC1583_COMPATIBLE))
736 {
737 ret = ospf_asbr_route_cmp (ospf, r1->u.ext.asbr, r2->u.ext.asbr);
738 if (ret != 0)
739 return ret;
740 }
741 break;
742 }
743
744 /* Anyway, compare the costs. */
745 return (r1->cost - r2->cost);
746 }
747
748 static int
749 ospf_path_exist (struct list *plist, struct in_addr nexthop,
750 struct ospf_interface *oi)
751 {
752 struct listnode *node, *nnode;
753 struct ospf_path *path;
754
755 for (ALL_LIST_ELEMENTS (plist, node, nnode, path))
756 if (IPV4_ADDR_SAME (&path->nexthop, &nexthop) &&
757 path->ifindex == oi->ifp->ifindex)
758 return 1;
759
760 return 0;
761 }
762
763 void
764 ospf_route_copy_nexthops_from_vertex (struct ospf_route *to,
765 struct vertex *v)
766 {
767 struct listnode *node;
768 struct ospf_path *path;
769 struct vertex_nexthop *nexthop;
770 struct vertex_parent *vp;
771
772 assert (to->paths);
773
774 for (ALL_LIST_ELEMENTS_RO (v->parents, node, vp))
775 {
776 nexthop = vp->nexthop;
777
778 if (nexthop->oi != NULL)
779 {
780 if (! ospf_path_exist (to->paths, nexthop->router, nexthop->oi))
781 {
782 path = ospf_path_new ();
783 path->nexthop = nexthop->router;
784 path->ifindex = nexthop->oi->ifp->ifindex;
785 if (CHECK_FLAG(nexthop->oi->connected->flags, ZEBRA_IFA_UNNUMBERED))
786 path->unnumbered = 1;
787 listnode_add (to->paths, path);
788 }
789 }
790 }
791 }
792
793 struct ospf_path *
794 ospf_path_lookup (struct list *plist, struct ospf_path *path)
795 {
796 struct listnode *node;
797 struct ospf_path *op;
798
799 for (ALL_LIST_ELEMENTS_RO (plist, node, op))
800 {
801 if (!IPV4_ADDR_SAME (&op->nexthop, &path->nexthop))
802 continue;
803 if (!IPV4_ADDR_SAME (&op->adv_router, &path->adv_router))
804 continue;
805 if (op->ifindex != path->ifindex)
806 continue;
807 return op;
808 }
809 return NULL;
810 }
811
812 void
813 ospf_route_copy_nexthops (struct ospf_route *to, struct list *from)
814 {
815 struct listnode *node, *nnode;
816 struct ospf_path *path;
817
818 assert (to->paths);
819
820 for (ALL_LIST_ELEMENTS (from, node, nnode, path))
821 /* The same routes are just discarded. */
822 if (!ospf_path_lookup (to->paths, path))
823 listnode_add (to->paths, ospf_path_dup (path));
824 }
825
826 void
827 ospf_route_subst_nexthops (struct ospf_route *to, struct list *from)
828 {
829
830 list_delete_all_node (to->paths);
831 ospf_route_copy_nexthops (to, from);
832 }
833
834 void
835 ospf_route_subst (struct route_node *rn, struct ospf_route *new_or,
836 struct ospf_route *over)
837 {
838 route_lock_node (rn);
839 ospf_route_free (rn->info);
840
841 ospf_route_copy_nexthops (new_or, over->paths);
842 rn->info = new_or;
843 route_unlock_node (rn);
844 }
845
846 void
847 ospf_route_add (struct route_table *rt, struct prefix_ipv4 *p,
848 struct ospf_route *new_or, struct ospf_route *over)
849 {
850 struct route_node *rn;
851
852 rn = route_node_get (rt, (struct prefix *) p);
853
854 ospf_route_copy_nexthops (new_or, over->paths);
855
856 if (rn->info)
857 {
858 if (IS_DEBUG_OSPF_EVENT)
859 zlog_debug ("ospf_route_add(): something's wrong !");
860 route_unlock_node (rn);
861 return;
862 }
863
864 rn->info = new_or;
865 }
866
867 void
868 ospf_prune_unreachable_networks (struct route_table *rt)
869 {
870 struct route_node *rn, *next;
871 struct ospf_route *or;
872
873 if (IS_DEBUG_OSPF_EVENT)
874 zlog_debug ("Pruning unreachable networks");
875
876 for (rn = route_top (rt); rn; rn = next)
877 {
878 next = route_next (rn);
879 if (rn->info != NULL)
880 {
881 or = rn->info;
882 if (listcount (or->paths) == 0)
883 {
884 if (IS_DEBUG_OSPF_EVENT)
885 zlog_debug ("Pruning route to %s/%d",
886 inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen);
887
888 ospf_route_free (or);
889 rn->info = NULL;
890 route_unlock_node (rn);
891 }
892 }
893 }
894 }
895
896 void
897 ospf_prune_unreachable_routers (struct route_table *rtrs)
898 {
899 struct route_node *rn, *next;
900 struct ospf_route *or;
901 struct listnode *node, *nnode;
902 struct list *paths;
903
904 if (IS_DEBUG_OSPF_EVENT)
905 zlog_debug ("Pruning unreachable routers");
906
907 for (rn = route_top (rtrs); rn; rn = next)
908 {
909 next = route_next (rn);
910 if ((paths = rn->info) == NULL)
911 continue;
912
913 for (ALL_LIST_ELEMENTS (paths, node, nnode, or))
914 {
915 if (listcount (or->paths) == 0)
916 {
917 if (IS_DEBUG_OSPF_EVENT)
918 {
919 zlog_debug ("Pruning route to rtr %s",
920 inet_ntoa (rn->p.u.prefix4));
921 zlog_debug (" via area %s",
922 inet_ntoa (or->u.std.area_id));
923 }
924
925 listnode_delete (paths, or);
926 ospf_route_free (or);
927 }
928 }
929
930 if (listcount (paths) == 0)
931 {
932 if (IS_DEBUG_OSPF_EVENT)
933 zlog_debug ("Pruning router node %s", inet_ntoa (rn->p.u.prefix4));
934
935 list_delete (paths);
936 rn->info = NULL;
937 route_unlock_node (rn);
938 }
939 }
940 }
941
942 int
943 ospf_add_discard_route (struct route_table *rt, struct ospf_area *area,
944 struct prefix_ipv4 *p)
945 {
946 struct route_node *rn;
947 struct ospf_route *or, *new_or;
948
949 rn = route_node_get (rt, (struct prefix *) p);
950
951 if (rn == NULL)
952 {
953 if (IS_DEBUG_OSPF_EVENT)
954 zlog_debug ("ospf_add_discard_route(): router installation error");
955 return 0;
956 }
957
958 if (rn->info) /* If the route to the same destination is found */
959 {
960 route_unlock_node (rn);
961
962 or = rn->info;
963
964 if (or->path_type == OSPF_PATH_INTRA_AREA)
965 {
966 if (IS_DEBUG_OSPF_EVENT)
967 zlog_debug ("ospf_add_discard_route(): "
968 "an intra-area route exists");
969 return 0;
970 }
971
972 if (or->type == OSPF_DESTINATION_DISCARD)
973 {
974 if (IS_DEBUG_OSPF_EVENT)
975 zlog_debug ("ospf_add_discard_route(): "
976 "discard entry already installed");
977 return 0;
978 }
979
980 ospf_route_free (rn->info);
981 }
982
983 if (IS_DEBUG_OSPF_EVENT)
984 zlog_debug ("ospf_add_discard_route(): "
985 "adding %s/%d", inet_ntoa (p->prefix), p->prefixlen);
986
987 new_or = ospf_route_new ();
988 new_or->type = OSPF_DESTINATION_DISCARD;
989 new_or->id.s_addr = 0;
990 new_or->cost = 0;
991 new_or->u.std.area_id = area->area_id;
992 new_or->u.std.external_routing = area->external_routing;
993 new_or->path_type = OSPF_PATH_INTER_AREA;
994 rn->info = new_or;
995
996 ospf_zebra_add_discard (p);
997
998 return 1;
999 }
1000
1001 void
1002 ospf_delete_discard_route (struct route_table *rt, struct prefix_ipv4 *p)
1003 {
1004 struct route_node *rn;
1005 struct ospf_route *or;
1006
1007 if (IS_DEBUG_OSPF_EVENT)
1008 zlog_debug ("ospf_delete_discard_route(): "
1009 "deleting %s/%d", inet_ntoa (p->prefix), p->prefixlen);
1010
1011 rn = route_node_lookup (rt, (struct prefix*)p);
1012
1013 if (rn == NULL)
1014 {
1015 if (IS_DEBUG_OSPF_EVENT)
1016 zlog_debug("ospf_delete_discard_route(): no route found");
1017 return;
1018 }
1019
1020 or = rn->info;
1021
1022 if (or->path_type == OSPF_PATH_INTRA_AREA)
1023 {
1024 if (IS_DEBUG_OSPF_EVENT)
1025 zlog_debug ("ospf_delete_discard_route(): "
1026 "an intra-area route exists");
1027 return;
1028 }
1029
1030 if (or->type != OSPF_DESTINATION_DISCARD)
1031 {
1032 if (IS_DEBUG_OSPF_EVENT)
1033 zlog_debug ("ospf_delete_discard_route(): "
1034 "not a discard entry");
1035 return;
1036 }
1037
1038 /* free the route entry and the route node */
1039 ospf_route_free (rn->info);
1040
1041 rn->info = NULL;
1042 route_unlock_node (rn);
1043 route_unlock_node (rn);
1044
1045 /* remove the discard entry from the rib */
1046 ospf_zebra_delete_discard(p);
1047
1048 return;
1049 }
1050