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