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